题意:
n<=1e5
思路:
我的做法和题解有些不同
题解是维护A的单调栈算B的贡献,反过来再做一次
我是去掉起始位置不同这个限制条件先算总方案数,再把两个串内部不合法的方案数减去
式子展开之后是 sigma(lcp(i,j))-K*L*(L+1)/2+合法(i,j)对数,其中L为连续的height[i]>=K的区域长度
sigma(lcp(i,j))计算部分与BZOJ3238类似
1 #include<cstdio> 2 #include<cstring> 3 #include<string> 4 #include<cmath> 5 #include<iostream> 6 #include<algorithm> 7 #include<map> 8 #include<set> 9 #include<queue> 10 #include<vector> 11 using namespace std; 12 typedef long long ll; 13 typedef unsigned int uint; 14 typedef unsigned long long ull; 15 typedef pair<int,int> PII; 16 typedef vector<int> VI; 17 #define fi first 18 #define se second 19 #define MP make_pair 20 #define N 210000 21 #define MOD 1000000007 22 #define eps 1e-8 23 #define pi acos(-1) 24 #define oo 1000000000 25 26 char a[N],b[N]; 27 int n,i,s[N],sa[N],wa[N],wb[N],wc[N],wd[N],height[N],rank[N], 28 H[N],stk[N]; 29 ll ans,K,c[N],d[N]; 30 31 int read() 32 { 33 int v=0,f=1; 34 char c=getchar(); 35 while(c<48||57<c) {if(c=='-') f=-1; c=getchar();} 36 while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar(); 37 return v*f; 38 } 39 40 bool cmp(int *r,int a,int b,int l) 41 { 42 return r[a]==r[b]&&r[a+l]==r[b+l]; 43 } 44 45 void getsa(int *r,int *sa,int n,int m) 46 { 47 int *x=wa,*y=wb,j,p; 48 for(i=0;i<n;i++) wc[x[i]=r[i]]++; 49 for(i=1;i<m;i++) wc[i]+=wc[i-1]; 50 for(i=n-1;i>=0;i--) sa[--wc[x[i]]]=i; 51 for(j=1,p=1;p<n;j*=2,m=p) 52 { 53 p=0; 54 for(i=n-j;i<n;i++) y[p++]=i; 55 for(i=0;i<n;i++) 56 if(sa[i]>=j) y[p++]=sa[i]-j; 57 for(i=0;i<n;i++) wd[i]=x[y[i]]; 58 for(i=0;i<m;i++) wc[i]=0; 59 for(i=0;i<n;i++) wc[wd[i]]++; 60 for(i=1;i<m;i++) wc[i]+=wc[i-1]; 61 for(i=n-1;i>=0;i--) sa[--wc[wd[i]]]=y[i]; 62 swap(x,y); 63 p=1; x[sa[0]]=0; 64 for(i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; 65 } 66 } 67 68 void getheight(int *r,int *sa,int n) 69 { 70 int i,j,k=0; 71 for(i=1;i<=n;i++) rank[sa[i]]=i; 72 for(i=0;i<n;height[rank[i++]]=k) 73 { 74 if(k) k--; 75 j=sa[rank[i]-1]; 76 while(r[i+k]==r[j+k]) k++; 77 } 78 } 79 80 void init() 81 { 82 memset(s,0,sizeof(s)); 83 memset(sa,0,sizeof(sa)); 84 memset(wa,0,sizeof(wa)); 85 memset(wb,0,sizeof(wb)); 86 memset(wc,0,sizeof(wc)); 87 memset(wd,0,sizeof(wd)); 88 memset(height,0,sizeof(height)); 89 memset(rank,0,sizeof(rank)); 90 } 91 92 void solve(ll f,int L,int R) 93 { 94 //printf("%lld %d %d ",f,L,R); 95 for(int i=L-1;i<=R+1;i++) H[i]=height[i]; 96 for(int i=L;i<=R;i++) c[i]=d[i]=0; 97 stk[1]=L-1; H[L-1]=-oo; 98 int top=1; 99 for(int i=L;i<=R;i++) 100 { 101 while(top&&H[i]<H[stk[top]]) top--; 102 if(stk[top]==L-1) c[i]=L; 103 else c[i]=stk[top]+1; 104 stk[++top]=i; 105 } 106 stk[1]=R+1; H[R+1]=-oo; 107 top=1; 108 for(int i=R;i>=L;i--) 109 { 110 while(top&&H[i]<=H[stk[top]]) top--; 111 if(stk[top]==R+1) d[i]=R; 112 else d[i]=stk[top]-1; 113 stk[++top]=i; 114 } 115 ll tmp=0; 116 for(int i=L;i<=R;i++) tmp=tmp+(-c[i]+i+1)*(d[i]-i+1)*height[i]; 117 // printf("%lld ",tmp); 118 ll t=R-L+1; 119 tmp=tmp-K*(t+1)*t/2; 120 // printf("%lld ",tmp); 121 for(int i=L;i<=R;i++) tmp=tmp+(-c[i]+i+1)*(d[i]-i+1); 122 // printf("%lld ",tmp); 123 ans=ans+f*tmp; 124 } 125 126 127 int main() 128 { 129 freopen("poj3415.in","r",stdin); 130 freopen("poj3415.out","w",stdout); 131 while(scanf("%lld",&K)!=EOF) 132 { 133 if(K==0) break; 134 ans=0; 135 init(); 136 scanf("%s",a); 137 int n1=strlen(a); 138 scanf("%s",b); 139 int n2=strlen(b); 140 for(int i=0;i<n1;i++) 141 if('A'<=a[i]&&a[i]<='Z') s[i]=a[i]-'A'+2; 142 else s[i]=a[i]-'a'+28; 143 s[n1]=1; 144 n=n1; 145 getsa(s,sa,n+1,100); 146 getheight(s,sa,n); 147 148 int i=1; 149 while(i<n) 150 { 151 i++; 152 if(height[i]>=K) 153 { 154 int st=i; 155 while(i<=n&&height[i]>=K) i++; 156 if(st<=i-1) solve(-1,st,i-1); 157 } 158 } 159 //printf("%lld ",ans); 160 161 162 init(); 163 for(int i=0;i<n2;i++) 164 if('A'<=b[i]&&b[i]<='Z') s[i]=b[i]-'A'+2; 165 else s[i]=b[i]-'a'+28; 166 s[n2]=1; 167 n=n2; 168 getsa(s,sa,n+1,100); 169 getheight(s,sa,n); 170 i=1; 171 while(i<n) 172 { 173 i++; 174 if(height[i]>=K) 175 { 176 int st=i; 177 while(i<=n&&height[i]>=K) i++; 178 if(st<=i-1) solve(-1,st,i-1); 179 } 180 } 181 // printf("%lld ",ans); 182 183 init(); 184 for(int i=0;i<n1;i++) 185 if('A'<=a[i]&&a[i]<='Z') s[i]=a[i]-'A'+2; 186 else s[i]=a[i]-'a'+28; 187 s[n1]=1; 188 for(int i=0;i<n2;i++) 189 if('A'<=b[i]&&b[i]<='Z') s[n1+i+1]=b[i]-'A'+2; 190 else s[n1+i+1]=b[i]-'a'+28; 191 s[n1+n2+1]=0; 192 n=n1+n2+1; 193 getsa(s,sa,n+1,100); 194 getheight(s,sa,n); 195 // for(int i=1;i<=n;i++) printf("%d ",sa[i]); 196 i=1; 197 while(i<n) 198 { 199 i++; 200 if(height[i]>=K) 201 { 202 int st=i; 203 while(i<=n&&height[i]>=K) i++; 204 if(st<=i-1) solve(1,st,i-1); 205 } 206 } 207 //for(int i=0;i<=n1+n2;i++) printf("%d ",sa[i]); 208 //for(int i=2;i<=n1+n2+2;i++) printf("%d ",height[i]); 209 printf("%lld ",ans); 210 } 211 return 0; 212 } 213