又是孙大大的模板..
本来想在有什么方法在O(n)里搞出来 结果就是发明了WA数组..
听了讲解才知道怎么做 然后终于由WA变成PE了了了了....
话说少了个回车比赛会扣分吗?应该扣吧..
这道题给height数组分段算 好像有道题和这个很像
height[i]>=k 并且连着的算一段 如果这一段有至少一个符合条件(不重叠)的 那么ans++
我这里是用暴力写的 写完以后想想好像是单调栈啊!
不过竟然暴力过了就不写了 - -
#include <algorithm> #include <cstring> #include <cstdio> using namespace std; const int maxn=3e5*2+10; /****************************************************************** ** 后缀数组 Suffix Array ** INIT:solver.call_fun(char* s); ** CALL: solver.lcp(int i,int j); //后缀i与后缀j的最长公共前缀 ** SP_USE: solver.LCS(char *s1,char* s2); //最长公共字串 ******************************************************************/ struct SuffixArray{ int r[maxn]; int sa[maxn],rank[maxn],height[maxn]; int t[maxn],t2[maxn],c[maxn],n; int m;//模板长度 void init(char* s){ n=strlen(s); for (int i=0;i<n;i++) r[i]=int(s[i]); m=300; } int cmp(int *r,int a,int b,int l){ return r[a]==r[b]&&r[a+l]==r[b+l]; } /** 字符要先转化为正整数 待排序的字符串放在r[]数组中,从r[0]到r[n-1],长度为n,且最大值小于m。 所有的r[i]都大于0,r[n]无意义算法中置0 函数结束后,结果放在sa[]数组中(名次从1..n),从sa[1]到sa[n]。s[0]无意义 **/ void build_sa(){ int i,k,p,*x=t,*y=t2; r[n++]=0; for (i=0;i<m;i++) c[i]=0; for (i=0;i<n;i++) c[x[i]=r[i]]++; for (i=1;i<m;i++) c[i]+=c[i-1]; for (i=n-1;i>=0;i--) sa[--c[x[i]]]=i; for (k=1,p=1;k<n;k*=2,m=p){ for (p=0,i=n-k;i<n;i++) y[p++]=i; for (i=0;i<n;i++) if (sa[i]>=k) y[p++]=sa[i]-k; for (i=0;i<m;i++) c[i]=0; for (i=0;i<n;i++) c[x[y[i]]]++; for (i=1;i<m;i++) c[i]+=c[i-1]; for (i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1; x[sa[0]]=0; for (i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],k)?p-1:p++; } n--; } /** height[2..n]:height[i]保存的是lcp(sa[i],sa[i-1]) rank[0..n-1]:rank[i]保存的是原串中suffix[i]的名次 **/ void getHeight(){ int i,j,k=0; for (i=1;i<=n;i++) rank[sa[i]]=i; for (i=0;i<n;i++){ if (k) k--; j=sa[rank[i]-1]; while (r[i+k]==r[j+k]) k++; height[rank[i]]=k; } } void call_fun(char* s){ init(s);//初始化后缀数组 build_sa();//构造后缀数组sa getHeight();//计算height与rank /* for(int i=0;i<=n;i++) printf("%d\t",i); puts("SA:"); for(int i=0;i<=n;i++) printf("%d\t",sa[i]); puts(""); puts("RK:"); for(int i=0;i<=n;i++) printf("%d\t",rank[i]); puts(""); puts("H:"); for(int i=0;i<=n;i++) printf("%d\t",height[i]); puts(""); */ } int calc(int k) { int mx=sa[1],mn=sa[1],sz=0,ret=0; for(int i=2;i<=n;i++) { if(height[i]>=k) { sz++; mx=max(sa[i],mx); mn=min(sa[i],mn); } else { //printf("%d:<%d to %d>\n",i,mn,mx); if(mx-mn>=k) ret++; mx=sa[i]; mn=sa[i]; sz=0; } } if(sz&&mx-mn>=k) ret++; //printf("ret:%d %d\n\n",k,ret); return ret; } void run(char *s) { call_fun(s); long long ans=0; int len=n/2; for(int i=1;i<=len;i++) ans+=calc(i); printf("%lld\n",ans); } }solver; char s[10010]; int main() { scanf("%s",s); //char s[]="abbbbbbaaaa"; ///5 //char s[]="aaa"; ///1 //char s[]="abacabacaba"; ///15 solver.run(s); return 0 }