【BZOJ3413】匹配

Description

Input

第一行包含一个整数n(≤100000)。

第二行是长度为n的由0到9组成的字符串。

第三行是一个整数m。

接下来m≤5·10行,第i行是一个由0到9组成的字符串s,保证单行字符串长度小于等于10^5,所有字符串长度和小于等于3·10^6

Output

输出m行,第i行表示第si和S匹配所比较的次数。

Sample Input

7
1090901
4
87650
0901
109
090

Sample Output

7
10
3
4

题解:题目是问你截止到匹配之前,A串的每个位置与B串的LCP+1之和。这要利用到一个性质,两个后缀的lcp长度等于后缀树上两个点的lca的mx值。所以我们对A串的反串建立后缀自动机,得到后缀树,然后将B串放到后缀树中进行匹配(后缀树中匹配不同于后缀自动机中的匹配,实现比较复杂,方法也有很多,可以看代码)。如果没有成功匹配,则我们取最后一个成功匹配的节点,从这个点沿着到根的路径一路走上去跑一个树形DP即可。如果匹配成功,我们记录一下匹配成功的节点以及匹配位置,然后离线处理。我们将原串中的点一个一个加到后缀树中去,用树状数组维护DFS序得到子树和,处理询问时依旧跑类似于树形DP的东西即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int N=200010; int n,m,tot,last,cnt;
char S[N],T[N];
int ch[N][10],mx[N],pre[N],p1[N],p2[N],mn[N],pos[N],qos[N],len[N],s[N],L[N],R[N],son[N][10],siz[N];
vector<int> q[N];
vector<int>::iterator it;
int f[N];
ll ans[N];
inline int extend(int x)
{
int p=last,np=++tot; last=np;
mx[np]=mx[p]+1,siz[np]=1;
for(;p&&!ch[p][x];p=pre[p]) ch[p][x]=np;
if(!p) ch[1][x]=np,pre[np]=1;
else
{
int q=ch[p][x];
if(mx[q]==mx[p]+1) pre[np]=q;
else
{
int nq=++tot; mx[nq]=mx[p]+1,R[nq]=R[q]-(mx[q]-mx[p]-1);
pre[nq]=pre[q],pre[np]=pre[q]=nq;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
for(;p&&ch[p][x]==q;p=pre[p]) ch[p][x]=nq;
}
}
return np;
}
void dfs(int x)
{
p1[x]=++p2[0];
for(int i=0,y;i<10;i++) if((y=son[x][i])) dfs(y),siz[x]+=siz[y],mn[x]=min(mn[x],mn[y]);
p2[x]=p2[0];
}
inline void updata(int x)
{
for(int i=x;i<=tot;i+=i&-i) s[i]++;
}
inline int query(int x)
{
int ret=0,i;
for(i=x;i;i-=i&-i) ret+=s[i];
return ret;
}
int main()
{
scanf("%d%s",&n,S);
int i,j,x,y;
memset(mn,0x3f,sizeof(mn));
tot=last=1;
for(i=n-1;i>=0;i--) pos[i]=extend(S[i]-'0'),mn[pos[i]]=i,R[pos[i]]=n-1;
for(i=2;i<=tot;i++) L[i]=R[i]-(mx[i]-mx[pre[i]])+1,son[pre[i]][S[L[i]]-'0']=i;
scanf("%d",&m);
dfs(1);
R[1]=-1;
for(i=1;i<=m;i++)
{
scanf("%s",T),len[i]=strlen(T);
for(x=1,j=y=0;j<len[i];j++)
{
if(y<=R[x])
{
if(S[y]==T[j]) y++;
else break;
}
else
{
if(son[x][T[j]-'0']) x=son[x][T[j]-'0'],y=L[x]+1;
else break;
}
}
qos[i]=x;
if(j<len[i])
{
if(x==1) ans[i]=n;
else
{
ans[i]=n+1ll*siz[x]*min(mx[x]-mx[pre[x]],y-L[x]);
for(x=pre[x];x!=1;x=pre[x]) ans[i]+=1ll*(mx[x]-mx[pre[x]])*siz[x];
}
}
else
{
ans[i]=len[i]+mn[x];
if(mn[x]) q[mn[x]-1].push_back(i);
}
}
for(i=0;i<n;i++)
{
updata(p1[pos[i]]);
for(it=q[i].begin();it!=q[i].end();it++)
{
for(j=pre[qos[*it]];j;j=pre[j]) ans[*it]+=1ll*(mx[j]-mx[pre[j]])*(query(p2[j])-query(p1[j]-1));
}
}
for(i=1;i<=m;i++) printf("%lld\n",ans[i]);
return 0;
}

最新文章

  1. Plant Design Review Based on AnyCAD
  2. (10) 深入了解Java Class文件格式(九)
  3. React的Transaction浅析
  4. 【IOS笔记】Event Delivery: The Responder Chain
  5. Subset sum problem
  6. CUBRID学习笔记 36 在net中添加多行记录
  7. UISlide
  8. &lt;转载&gt;浅谈C/C++的浮点数在内存中的存储方式
  9. [原创] CSS总结!! 有关HTML第二篇 !!
  10. Linux命令总结(转载)
  11. Android系统移植与驱动开发——第五章--搭建开发板的测试环境
  12. Uber 司机有话说:你以为当个 Uber 司机很轻松?大错特错!
  13. qdoc 简介
  14. Spring装配bean
  15. Python 开发与接口测试学习笔记
  16. Java Cookie和Session
  17. Chrome 启动全屏,并可以F11退出
  18. Shell data、timedatectl
  19. [IR] Extraction-based Text Summarization
  20. 《Lua程序设计》第7章 迭代器与泛型for 学习笔记

热门文章

  1. 【Ubuntu】boot空间不足
  2. Window 10 :我的性能优化:那效果,杠杠的!
  3. getIsDebuggable
  4. 常用Linq示例代码
  5. Linux┊理解devfs、sysfs、udev、tmpfs等各种文件系统
  6. iOS中js与objective-c的交互(转)
  7. %s %d %f 等等是什么意思
  8. python与VScode
  9. 【Android】java.lang.RuntimeException: java.lang.Throwable: A WebView method was called on thread &#39;JavaBridge&#39;.
  10. python commands模块在python3.x被subprocess取代