太久不写,比赛时都不敢直接敲了...
Kuala2011 G
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
char a[200000],b[200000],ch[200000];
int n,m,len,f[200000],t;
int main()
{
freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
scanf("%d",&t);
for (;t;t--) {
scanf("%s",a+1);
scanf("%s",b+1);
n=strlen(a+1),m=strlen(b+1);
len=0;
for (int i=1;i<=m;i++) ch[++len]=b[i];
ch[++len]='$';
for (int i=1;i<=n;i++) ch[++len]=a[i];
int j;
f[1]=0,j=1;
for (int i=2;i<=len;i++) {
if (j+f[j]>=i) f[i]=min(f[i-j+1],j+f[j]-i);else f[i]=0;
f[i]=max(f[i],0);
for (;(f[i]>=0) && (i+f[i]<=len) && (ch[1+f[i]]==ch[i+f[i]]);) f[i]++;
f[i]--;
if (i+f[i]>j+f[j]) j=i;
}
int ans=1;
//for (int i=1;i<=len;i++) cout<<f[i]<<' ';cout<<endl;
for (int i=m+2;i<=len;i++)
if (i+f[i]==len) ans++;
printf("%d\n",ans);
}
return 0;
}
定义函数R(X),表示把X这个字符串翻转:
R(‘ASD’)=’DSA’;
R(‘aaa’)=’aaa’;
再定义函数F(s,i,j),其中F的自变量s为字符串,i、j为0到N-1的整数,i<j:
f(s, i, j) = s[i + 1... j - 1] + r(s[j... n - 1]) + r(s[0... i]).
//”+”即为字符串首尾相接,这个字符串下标为0~n-1,s[i…j]表示从下标i到下标j的子串。
有两个字符串A,B,要求出i、j,满足F(A,i,j)=B;
如果没有这样的i,j,输出“-1 -1”;
如果有多组解,首先令i最大,然后令j最小。
考虑枚举i的位置,那么B的后半段和A的前半段可以确定i是否可行,然后B的开头就确定是i+1了,我们将B+A求一次拓展kmp,可知道在B的前1+f[i+1]中的k都是一个可能的j-1,
同时为了使A[n~k+1]==B[k+1~i],再对r(A)+B求一次拓展kmp,如果k+1+g[k+1]>=n-i的话,k就是可行的,因此这样就是在二维偏序中求极值,o(nlogn)的时间就可以解决
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
const int oo=1073741819;
using namespace std;
int f[2500000],g[2500000],n,m,m1;
int c[2500000],s[6000000],st[2500000];
char a[1500000],b[1500000];
bool cmp(int i,int j)
{
return min(1+f[i+1+m+1],n-i)<min(1+f[j+1+m+1],n-j);
}
void change(int x,int w)
{
for (x+=m1;x;x>>=1) s[x]=min(s[x],w);
}
int ask(int l,int r)
{
int sum=oo;
l+=m1-1,r+=m1+1;
for (;!((l^r)==1);l>>=1,r>>=1) {
if ((l&1)==0) sum=min(sum,s[l+1]);
if ((r&1)==1) sum=min(sum,s[r-1]);
}
return sum;
}
int main()
{
freopen("trans.in","r",stdin);
freopen("trans.out","w",stdout);
//scanf("%s",a+1);
//scanf("%s",b+1);
gets(a+1);
gets(b+1);
n=strlen(a+1),m=strlen(b+1);
if (n!=m) {
printf("-1 -1\n");
return 0;
}
for (int i=1;i<=m;i++) c[i]=b[i];
c[m+1]=1000;
for (int i=1;i<=n;i++) c[i+m+1]=a[i];
//for (int i=1;i<=n+m+1;i++) cout<<c[i]<<' ';cout<<endl;
int j=1;f[1]=0;
for (int i=2;i<=n+m+1;i++) {
if (j+f[j]>=i) f[i]=min(f[i-j+1],j+f[j]-i);
else f[i]=0;
f[i]=max(f[i],0);
for (;(f[i]>=0) && (i+f[i]<=n+m+1) && (c[1+f[i]]==c[i+f[i]]);) f[i]++;
f[i]--;
if (i+f[i]>j+f[j]) j=i;
}
//for (int i=1;i<=n+m+1;i++) cout<<f[i]<<' '<<endl;
for (int i=n;i>=1;i--) c[n-i+1]=a[i];
c[n+1]=1000;
for (int i=1;i<=m;i++) c[i+n+1]=b[i];
j=1,g[1]=0;
for (int i=2;i<=n+m+1;i++) {
if (j+g[j]>=i) g[i]=min(g[i-j+1],j+g[j]-i);
else g[i]=0;
g[i]=max(g[i],0);
for (;(g[i]>=0) && (i+g[i]<=n+m+1) && (c[1+g[i]]==c[i+g[i]]);) g[i]++;
g[i]--;
if (i+g[i]>j+g[j]) j=i;
}
int r=0;
for (int i=1;(i<n-1) && (a[i]==b[m-i+1]);i++) st[++r]=i;
if (!r) {
printf("-1 -1\n");
return 0;
}
sort(st+1,st+r+1,cmp);
for (m1=1;m1<=n+m+2;m1<<=1) ;
for (int i=m1+m1;i>=1;i--) s[i]=oo;
int ansi=-1,ansj=-1;
if (f[n+1+1]==n-1) ansi=n-1,ansj=n;
for (int i=1,k=1;i<=r;i++) {
if (f[st[i]+1+m+1]<0) continue;
for (;(k+1<=n) && (k<=min(1+f[st[i]+1+m+1],n-st[i]));k++) change(k+1+g[k+1+n+1],k);
int tmp=ask(n-st[i],n+m);
//cout<<st[i]<<' '<<k<<endl;
if (tmp>=oo) continue;
if (st[i]>ansi) ansi=st[i],ansj=tmp+st[i]+1;
}
printf("%d %d\n",ansi-1,ansj-1);
return 0;
}