对于询问为长度为len的字符串,原字符串中长度为len的字符串一共只有n-len+1个,所以字符串hash以后最多有n-len+1个字符串的不同数值,而且询问字符串任意变异类型,字符串一定是不一样的,所以可以放心大胆dfs,dfsn-len+1次以后,一定就能找到,要么就没有n-len+1那么多种变异,就有可能为impossible。
以前TB说过字符串hash直接用两个大素数进行%,然后set存起来,还说bzoj上专门有这样的一个题让你出数据卡他,至今AC未0,所以保存对两个大素数取模的hash值是非常唯一的,几乎不可能重合,不然就公共溢出区(qt数组版不要用vector,很慢很容易爆空间),或者开放寻址法。
然而这道题不知道为撒一直A不了,看了其他人的代码发现可以直接一个素数取模,甚至不用冲突处理。。。数据有点水,然而这样写又因为ans没有初始化导致疯狂WA。。。。我真是去一头撞死算了,上次第一次打cfdiv1,A题因为开小数组,WA了一发,然后过了6分钟才发现开小数组。。。光速掉会蓝名,我这个学期的离散和高数也是,各种奇怪出错,什么时候才能减少粗心出错啊。。。什么long long ,初始化,数组大小,输出格式,i写成l,取模负数没处理。都WA过无数次了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
#define maxl 10010
#define mod 12255871
using namespace std;
int n,m,len,h;
char s[maxl];
int a[maxl],b[maxl],ans[maxl];
int mi[maxl],c[maxl];
struct query
{
int a,b,ind;
}q[1010];
bool flag;
bool vis[maxl];
set <int> P;
bool cmp(const query &x,const query &y)
{
return (x.b-x.a+1)<(y.b-y.a+1);
}
inline void prework()
{
scanf("%s",s+1);
for(int i=1;i<=n;i++)
a[i]=s[i]-'0';
for(int i=1;i<=m;i++)
{
scanf("%d%d",&q[i].a,&q[i].b);
q[i].ind=i;
}
sort(q+1,q+1+m,cmp);
}
inline void init(int l)
{
for(int i=1;i<=c[0];i++)
P.erase(c[i]);
P.clear();
c[0]=0;
int num=0;
for(int i=1;i<=l;i++)
num=((num<<1)+a[i])%mod;
P.insert(num);
c[++c[0]]=num;
for(int i=l+1;i<=n;i++)
{
num=(num-a[i-l]*mi[l-1]+mod)%mod;
num=((num<<1)+a[i]+mod)%mod;
c[++c[0]]=num;
P.insert(num);
}
}
void dfs(int k,int last,int num)
{
if(k==h)
{
if(P.find(num)==P.end())
flag=true;
return;
}
int lastnum=num;
for(int i=last+1;i<=len-h+k+1 && !flag;i++)
if(!vis[i])
{
vis[i]=true;
num=(num-mi[len-i]*b[i])%mod;
num=(num+mod)%mod;
num=(num+mi[len-i]*(b[i]^1))%mod;
dfs(k+1,i,num);
num=lastnum;
vis[i]=false;
}
}
inline void mainwork()
{
int num;
q[0].a=1;q[0].b=0;
for(int i=1;i<=m;i++)
{
if(q[i].b-q[i].a+1!=q[i-1].b-q[i-1].a+1)
init(q[i].b-q[i].a+1);
for(int j=q[i].a;j<=q[i].b;j++)
b[j-q[i].a+1]=a[j];
flag=false;
len=q[i].b-q[i].a+1;
memset(vis,false,sizeof(vis));
num=0;
for(int j=1;j<=len;j++)
num=((num<<1)+b[j])%mod;
for(int j=1;j<=n && !flag;j++)
{
h=j;
dfs(0,0,num);
if(flag)
{
ans[q[i].ind]=j;
break;
}
}
if(!flag)
ans[q[i].ind]=0;
}
}
inline void print()
{
for(int i=1;i<=m;i++)
if(ans[i])
printf("%d\n",ans[i]);
else
printf("Impossible\n");
}
int main()
{
mi[0]=1;
for(int i=1;i<maxl;i++)
mi[i]=(mi[i-1]<<1)%mod;
while(~scanf("%d%d",&n,&m))
{
if(n==0 && m==0)
break;
prework();
mainwork();
print();
}
return 0;
}