#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); } };