华为机试HJ32:密码截取

Posted 翟天保Steven

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了华为机试HJ32:密码截取相关的知识,希望对你有一定的参考价值。

题目描述:

该题目是一道密码加密题,密码混合在复杂字符串中,是一个对称子字符串,比如12321AABC,则真正要提取的是12321,因为它是对称的,所以需要写一个程序来实现快速的提取。

题目要求提取最长的密码长度。

输入描述:

输入一个字符串

输出描述:

返回有效密码串的最大长度

示例:

输入:

12321AABC

输出:

5

解题思路:

该题其实应该属于动态规划,若某字符串存在某段回文,则将该字符串反转后,该回文依然存在,基于此逻辑可建立二分图,一层层寻找最长的重复子字符串,但是该方法的弊端就是空间复杂度太高了,放在这个题目了没法AC。

只能采用暴力破解了,从左右侧循环分析,固定某段字符串,将其两头缩进判断,若存在非对称点,则跳出并判断该段不是回文;若找到某段字符串是回文,跳出一层循环,因为该层循环下即使再找到回文也是更短的,你品你细品;最后输出最大值,完成。

测试代码:

#include <iostream>
#include <algorithm> 
#include <vector>
using namespace std;

int main(){
    string str;
    vector<int> result;
    while(cin>>str){
        int maxn=1,flag=0;
        //暴力循环,分别从左右侧分析
        for(int i=0;i<str.length();i++){
            for(int j=str.length()-1;j>i;j--){
                //flag为0则说明该段是回文
                flag=0;
                int l,r;
                //判断该段是否为回文 
                for(l=i,r=j;l<=(i+j)/2;l++,r--){ 
                    if(str[l]!=str[r]){
                        flag=1;
                        break;
                    }
                }
                //若该长段为回文,则此级遍历进行下去也只能找到更短的回文,为提速可直接跳出循环
                if(flag==0){
                    maxn=max(maxn,(j-i+1));
                    break; 
                }
            }
        }
        result.push_back(maxn);
    }
    for(auto i:result)
    {
        cout<<i<<endl;
    }
    return 0;
}

       动态规划的解法:

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
int CalcSymStringMaxLength(string str) {
    string left = str; 
    reverse(str.begin(), str.end());   // 反转字符串,若存在回文,则str与反转后的str存在同一子字符串
    string right = str; 
    int len1 = left.size();
    int len2 = right.size();
    int max = 0; 
    int** bp = new int* [len2];
    if (len1 == 0) {
        return 0;
    }
    if (len1 == 1) {
        return 1;
    }
    // 建立二分图
    for (int i = 0; i < len2; i++) {
        bp[i] = new int [len1];
    }
    for (int i = 0; i < len2; i++) {
        if (left[0] == right[i]) {
            bp[i][0] = 1;
        } else {
            bp[i][0] = 0;
        }
    }
    // 先确定边缘信息
    for (int i = 0; i < len1; i++) {
        if (left[i] == right[0]) {
            bp[0][i] = 1;
        } else {
            bp[0][i] = 0;
        }
    }
    for (int i = 1; i < len1; i++) {
        for (int j = 1; j < len2; j++) {
            if (left[i] == right[j]) {
                // 若bp[i - 1][j - 1]有值,则说明之前有一个回文,在此基础上再加1;若无值,相当于给bp[i][j]赋1
                bp[i][j] = bp[i - 1][j - 1] + 1;
            } else {
                bp[i][j] = 0;
            }
            // 刷新最大值
            if (bp[i][j] > max) {
                max = bp[i][j];
            }
        }
    }
    return max;
}
//主函数
int main () {
    string str;
    vector<int> result;
    while (cin >> str) {
        int temp=CalcSymStringMaxLength(str);
        result.push_back(temp);
    }
    for(auto i:result)
    {
        cout<<i<<endl;
    }
    return 0;
}

       动态规划的解法之所以空间不够,主要是因为用二维数组存放了太多数据,若字符串非常大时,这个数组也特别特别大,但是这个解法是最符合题意的,暴力破解太无脑了。。。

以上是关于华为机试HJ32:密码截取的主要内容,如果未能解决你的问题,请参考以下文章

华为机试HJ21:简单密码

华为机试HJ87:密码强度等级

华为机试HJ87:密码强度等级

华为机试HJ20:密码验证合格程序

华为机试HJ28:素数伴侣

华为机试HJ90:合法IP