主要是应用在回文串啦,原理也理解了老半天,如果没有图片的话,我也看不太懂它的原理
学习的灵感来源来自于:https://segmentfault.com/a/1190000008484167
/* 最长回文 */ /*给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 回文就是正反读都是一样的字符串,如aba, abba等 Input 输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S 两组case之间由空行隔开(该空行不用处理) 字符串长度len <= 110000 Output 每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度. Sample Input aaaa abab Sample Output 4 3*/ #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <cmath> using namespace std; /*说实话我非常讨厌字符串的题目,对于我来说可能是会在输入出现问题,所以我一直都不 太喜欢字符串,拿到这道题是没有什么思路的。但是简单看了解析就不得不佩服他们的想法 他的想法是,在每个字符串之间加入特殊符号,他用的是#,这样子就可以算出奇数个的回 文串了,这样奇数字符串就仍然以字母为中心,偶数字符串就会以#为中心展开,接下来的 方法我还没看,但我可以猜测如果是检索到#的话就隔项去检索字母,如果是检索到字母就 隔项去检索字母,试着去完成一下吧*/ //果然还是以失败告终,我去看看网上的思路吧 char s[110050], ss[220100]; int Count[220100]; int judge( int len ) { Count[0]=1;//最低限度是1,但这个点应该用不到的说= =,这句话应该可以删掉 int mx=0,id=0; //mx 代表以 id 为中心的最长回文的右边界 for(int i=1 ; i<=len ; i++ ) //从第一个#开始 { if( mx>i )//如果这个点包含在右边界之中 { Count[i] = min( Count[2*id-i] , mx-i ); /*这句话简直太精辟了,在id的右边的点i,会等于id左边点的对称点,如果 这个i点到id的点的距离(左段)和i点到mx点的距离(右段)相比,如果右边 比较小,那么就会继续向mx外部检索,如果对称点的Count[2*id-i]还不及边 界,那么就不必继续向外检索了,下面的循环第一步就会停止了*/ } else { Count[i] = 1;//如果这个点超出了右边界,那么这个点开始重新计算 } while( i+Count[i]<=len && ss[i-Count[i]]==ss[ i+Count[i] ] ) Count[i]++;//如果旁边只要有一次相等便会+1,直到不相等为止 if( Count[i]+i > mx )//如果新检索的位置超出了最大边界 { mx=Count[i]+i;//Count存储的是半径,i是当前位置,相加得新的右边界 id=i;//id记录的是对称点所在位置 } } //数据验证 /*for (int i=1 ; i<=len ; i++ ) { cout<<Count[i]<<' '; } cout<<endl;*/ int max=0; for(int i=1;i<=len;i++) { if( Count[i] > max ) max=Count[i]; } return max-1; } int main(void) { int result; int j, len, i; ss[0]='$'; ss[1]='#'; while ( scanf("%s",s)!=EOF ) { j=2; len=strlen(s); for ( i=0 ; i<len ; i++ ) { ss[j++]=s[i]; ss[j++]='#';//执行完语句j才会自增1 } //ss[j]='^'; //printf("%s\n",ss); result = judge(j); printf("%d\n",result); } return 0; } //下面这里是自己实现的代码,貌似不太行23333 /*int judge( int len ) { len=(len+1)*2+1;//比ss多一个数字,是小于 int max=0, i=3 , count=1; while ( i<len ) { if ( ss[i]=='#' ) { while ( 1 ) { if ( (i-count*2+1)>=0 || (i+count*2-1)>=len ) break; if ( ss[i-count*2+1] == ss[i+count*2-1] ) { if ( count > max ) max=count; count++; } else { count=1; break; } } } else { while ( 1 ) { if ( ss[i+count*2] == ss[i-count*2]) { if ( count > max ) max=count; count++; } else { count=1; break; } if ( (i-count*2)>=0 || (i+count*2)>=len ) break; } } i++; } return max; }*/