一开始只是想刷刷水题然后半小时打好代码(用的是指针,后来发现自己MLE然后改成数组 然后又T(因为用了map 然后又改成指针 最后又手打hash 最后丧心病狂卡空间 还好codevs上可以看自己的错误信息 此处感谢wphorzorz
其实一开始看到题目我们应该想得到这一题就是裸的ac自动机上的失配边构成的树的树上lca(有点绕 如果不理解仔细想想 这个很重要) 一开始傻逼没有存每个节点对应的编码果断T了 后来才发现每个点的编码可以预先搞出来=。=
#include
#include
#include
using namespace std;
#define min(a,b) (a
#define youhua __attribute__((optimize("O2")))
int con=1;
int root=1;
struct node
{
int len;
short data;
int ff,ch[26],f[19 ];
int ans;
youhua inline node(int fa,shortda){ff=fa;for(len=0;len<26;len++)f[min(len,18)]=ch[len]=0;len=0;data=da;ans=0;};
youhua inlinenode(){ff=0;for(len=0;len<26;len++)f[min(len,18)]=ch[len]=0;len=0;data=-1;ans=0;}
}ac[1001001];
char c;
//youhua inline void read(int &a)
//{
// a=0;
// do c=getchar();while(c<'0'||c>'9');
//while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
//}
char s1[1000001];
int line[1001001];
struct Node
{
int x,y;
youhua inline friend bool operator ==(Nodea,Node b)
{ return (a.x==b.x&&a.y==b.y); }
youhua inline friend bool operator !=(Nodea,Node b)
{ return (a.x!=b.x||a.y!=b.y); }
};
struct chain{
Node a;
chain *next;
int data;
youhua chain(Node sa,chain *b,int ad){a=sa,next=b,data=ad;}
};
long long place;
struct hillan
{
chain *head[1007001];
chain *temp;
youhua inline void push(int i,int j,int k)
{
place=(i*13237ll+j)07000;
head[place]=new chain((Node){i,j},head[place],k);
}
youhua inline int find(int i,int j)
{
place=(i*13237ll+j)07000;
for(temp=head[place];temp->a.x!=i&&temp->a.y!=j;temp=temp->next);
return temp->data;
}
}m;
const
long long mod=1000000007;
//map mm;
int j,len1,i,temp;
long long res;
youhua inline void insert()
{
res=1;
temp=root;
for(j=0;j
//mm[(Node){i,j}]=ac[temp].ch[s1[j]-'a'],temp=ac[temp].ch[s1[j]-'a'];
res*=26,m.push(i,j,ac[temp].ch[s1[j]-'a']),temp=ac[temp].ch[s1[j]-'a'];
for(;j
ac[++con].data=s1[j]-'a';
ac[con].ff=temp;
ac[con].ans=(ac[ac[con].ff].ans*26ll+s1[j]-'a')%mod;
res*=26;
res%=mod;
temp=ac[temp].ch[s1[j]-'a']=con;
m.push(i,j,con);}//mm[(Node){i,j}]=con;
if(con>1001000)
printf("MLE"),exit(0);
}
int l,r;
youhua inline void build()
{
l=1,r=1;
line[l]= root;
ac[root].f[0]=0;
for(i=0;i<26;i++)
if(ac[line[l]].ch[i])line[++r]=ac[line[l]].ch[i];
while(++l<=r)
{
temp=ac[ac[line[l]].ff].f[0];
for(;temp&&!ac[temp].ch[ac[line[l]].data];temp=ac[temp].f[0]);
if(!temp)
ac[line[l]].f[0]=root;
elseac[line[l]].f[0]=ac[temp].ch[ac[line[l]].data];
ac[line[l]].len=ac[ac[line[l]].f[0]].len+1;
//- addside(line[l]->f[0],line[l]);
for(i=0;i<26;i++)
if(ac[line[l]].ch[i])line[++r]=ac[line[l]].ch[i];
}
ac[line[1]].f[0]=line[1];
for(i=1;i<=r;i++)
for(j=1;j<=18;j++)
ac[line[i]].f[j]=ac[ac[line[i]].f[j-1]].f[j-1];
}
//youhua inline void read(char *a)
//{
// len1=-1;
// do c=getchar();while(c<'a'||c>'z');
//while(c<='z'&&c>='a')a[++len1]=c,c=getchar();len1++;
//}
youhua int main()
{
int n;i=1;
//read(n);
n=0;
do c=getchar();while(c<'0'||c>'9');
while(c<='9'&&c>='0')n=(n<<3)+(n<<1)+c-'0',c=getchar();
while(i<=n)
{
// read(s1);
// scanf("%s",s1);
len1=-1;
doc=getchar();while(c<'a'||c>'z');
while(c<='z'&&c>='a')s1[++len1]=c,c=getchar();len1++;
insert();
i++;
}
build();
int i;
//read(n);
n=0;
do c=getchar();while(c<'0'||c>'9');
while(c<='9'&&c>='0')n=(n<<3)+(n<<1)+c-'0',c=getchar();
int j,k,l,t;
int aa,bb;
// long long ans;
//long long res;
while(n--)
{
//read(i),read(j),read(k),read(l);
i=0;
do c=getchar();while(c<'0'||c>'9');
while(c<='9'&&c>='0')i=(i<<3)+(i<<1)+c-'0',c=getchar();
j=0;
do c=getchar();while(c<'0'||c>'9');
while(c<='9'&&c>='0')j=(j<<3)+(j<<1)+c-'0',c=getchar();
k=0;
do c=getchar();while(c<'0'||c>'9');
while(c<='9'&&c>='0')k=(k<<3)+(k<<1)+c-'0',c=getchar();
l=0;
do c=getchar();while(c<'0'||c>'9');
while(c<='9'&&c>='0')l=(l<<3)+(l<<1)+c-'0',c=getchar();
aa=m.find(i,j-1);
bb=m.find(k,l-1);
if(ac[aa].len
swap(aa,bb);
if(bb==root)
{
putchar('0');putchar('\n');
continue;
}
while(ac[aa].len!=ac[bb].len)
{
for(j=0;ac[ac[aa].f[j+1]].len>=ac[bb].len;j++) ;
aa=ac[aa].f[j];
}
while(aa!=bb)
{
for(j=0;ac[aa].f[j+1]!=ac[bb].f[j+1];j++);
aa=ac[aa].f[j];
bb=ac[bb].f[j];
}
// ans=0;
// res=1;
// while(aa!=root)
// {
// ans+=ac[aa].data*res;
// res*=26;
// ans%=mod;
// res%=mod;
// aa=ac[aa].ff;
// }
printf("%lld\n",ac[aa].ans);
}
return 0;
}