题目来源:(POJ 1961版) 点击打开链接
(HDU 1358版,这两个测试数据不一样)点击打开链接
KMP字符匹配题目,求整个序列中大于1个重复子串位置和数据,利用性质i/(i-next[i])和i%(i-next[i)来判断之,详情可以见这里。这个题POJ的测试数据比较严谨,有些写的不严谨的NEXT数组会被判错。很多人拙计的问为什么错了,下边给个反例,样例和下边的反例过了,你的NEXT函数基本就没有问题了。
举例子:10 abaababaab
正解是:6 2
10 2
错解只有第一个。
//经典Trap:10 abaababaab // 返回两组 6 2 // 10 2 #include <iostream> #include <string> #include <cstring> using namespace std; int next[1000009]; void get_next(string str) //第一个是-1,以后的直接用j=next[j]就行 ,next[1]开始真的有数 { int j=0,k=-1; next[0]=-1; while(j<str.size()) { if(k==-1||str[j]==str[k]) { j++; k++; next[j]=k; } else k=next[k]; } } int main() { int testcase; int test=1; while(cin>>testcase && testcase!=0) { string tar; cin>>tar; get_next(tar); cout<<"Test case #"<<test<<endl; for(int i=2;i<=testcase;i++) { if(i%(i-next[i])==0 && i/(i-next[i])>1) { cout<<i<<" "<<i/(i-next[i])<<endl; } } cout<<endl; test++; } return 0; }
void build_next(string b) { int i,j=0,key=0; memset(next,0,sizeof(next)); for(i=1;i<b.size();i++) { j=next[i-1]; while(j==1 && b[i]!=b[j]) { j=next[j-1]; } if(b[j]==b[i]) { next[i]=j+1; } else next[i]=0; } }