复杂字符串处理算法

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

vector<int> getNext(const string &s)
{
    if(s.size()==1)
        return vector<int>{-1};
    vector<int> next(s.size(), 0);
    next[0]=-1;
    next[1]=0;
    //开始匹配的位置是从2开始的,因为是不包含当前字符的最长前缀和最长后缀
    int pos = 2;
    int cn = 0;//指向的是还没有进行匹配的下一个数
    while(pos < s.size())
    {
        //如果相等 就都往后面移动
        if(s[pos-1] == s[cn])
        {
            next[pos++] = ++cn;
        }//如果不相等
        else
        {
            //如果cn已经来到了0位置,那就是都没有比对上
            if(cn == 0)
            {
                next[pos++]=0;
            }//否则就往前跳,调到next数组中对应的位置
            else
            {
                cn = next[cn];
            }
        }
    }
    return next;
}


int KMP(const string &s1, const string &s2)
{
    if(s1.size()==0 || s2.size()==0 || s1.size()<s2.size())
        return -1;

    auto next = getNext(s2);
    int idx1 = 0;
    int idx2 = 0;
    while(idx1 < s1.size() && idx2 < s2.size())
    {
        //相等情况
        if(s1[idx1] ==  s2[idx2])
        {
            idx1++;
            idx2++;
        }
        else//不等情况
        {
            //来到了第一个字符还不相等
            if(next[idx2] == -1)
            {
                idx1++;
            }
            else//转到next数组中对应的位置再次进行匹配
            {
                idx2 = next[idx2];
            }
        }
    }
    return idx2==s2.size() ? idx1-idx2 : -1;
}


int main()
{
    string s1 = "andyniu is me!";
    string s2 = "is";
    cout << KMP(s1,s2) << endl;
    return 0;
}
//为了解决字符串是奇数还是偶数的问题
vector<char> manacherString(const string& str)
{
    int len = str.size();
    vector<char> res(2*len+1, 0);
    int idx = 0;
    for(int i=0; i<res.size(); ++i)
    {
        res[i] = (i&1)==0 ? '#' : str[idx++];
    }
    return res;
}
vector<int> Manacher(const string& str)
{
    if(str.size()==0)
        return vector<int>{0};
    if(str.size()==1)
        return vector<int>{1};
    //至少有2个字符以上才进行判断
    vector<char> manStr = manacherString(str);
    vector<int> pRadius(manStr.size(), 0);
    int center = -1;
    int pR = -1;//始终是下一个即将匹配的字符,如果到了最后,表明已经结束了。
    //开始计算每一个字符
    for(int i=0; i<manStr.size(); ++i)
    {
        //可以直接括住的情况下直接可以计算出来对应的结果
        pRadius[i] = pR > i ? min(pR-i, pRadius[2*center-i]) : 1;
        //暴力扩 还在范围内
        while(i+pRadius[i] < manStr.size() && i-pRadius[i] >= 0)
        {
            //尝试进行扩
            if(manStr[i+pRadius[i]] == manStr[i-pRadius[i]])
                pRadius[i]++;
            else
                break;
        }
        if(i+pRadius[i]>pR)
        {
            pR = i + pRadius[i];
            center = i;
        }
    }
    return pRadius;
}


int main()
{
    string str = "212";
    auto ret = Manacher(str);
    for(const auto& ele : ret)
        cout << ele;
    cout << endl;
    return 0;
}
class Solution {
public:
    vector<int> getNext(const string &s)
    {
        if(s.size()==1)
            return vector<int>{-1};
        vector<int> next(s.size(), 0);
        next[0]=-1;
        next[1]=0;
        //开始匹配的位置是从2开始的,因为是不包含当前字符的最长前缀和最长后缀
        int pos = 2;
        int cn = 0;//指向的是还没有进行匹配的下一个数
        while(pos < s.size())
        {
            //如果相等 就都往后面移动
            if(s[pos-1] == s[cn])
            {
                next[pos++] = ++cn;
            }//如果不相等
            else
            {
                //如果cn已经来到了0位置,那就是都没有比对上
                if(cn == 0)
                {
                    next[pos++]=0;
                }//否则就往前跳,调到next数组中对应的位置
                else
                {
                    cn = next[cn];
                }
            }
        }
        return next;
    }
   
    bool isRepatedString(const string &str)
    {
        string ss =  str+'\n';
        auto next = getNext(ss);
        int len = str.size()-next[str.size()];//可能最后一个位置上面的元素是0,这样len的长度就和str.size()一样了,比如说abac这个例子中next结果为-1,0,0,1,0
        return len!=str.size() && str.size()%len == 0;
    }
    
    bool repeatedSubstringPattern(string s) {
        if(s.size()<2)
            return false;
        return isRepatedString(s);
    }
};

猜你喜欢

转载自www.cnblogs.com/randyniu/p/9483332.html