zoukankan      html  css  js  c++  java
  • hdu 6068 Classic Quotation

      QAQ http://acm.hdu.edu.cn/showproblem.php?pid=6068

      2017 Multi-University Training Contest - Team 4 - 1005

      贴一张官方题解

      

      其中S可以由O(n*m)的求前缀得到。

      求suf贼难,淦。

      求suf主要是通过类似DP的思想

      其中ismatch[i][j]表示T的匹配指针为i,匹配到字母j的时候,是否新匹配了一个完整的T串。

      nxt2[i][j]表示,当T的匹配指针为i,匹配到字母j的时候,T的指针转移到哪个位置

      然后未求前缀的suf数组就可以倒着DP出来了

      (思路来自某官方题解和某其他博客的题解)

      

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    
    typedef long long ll;
    
    const int M=5e4+44;
    const int N=244;
    
    int n,m,qur;
    char S[M],T[N];
    int nxt[N];
    int preg[M];
    int s[M][N];
    int suf[M][N];
    int ismatch[N][N],nxt2[N][N];
    
    void init()
    {
    	int i,j,k,tmp,tmpi,tmpj;
    
    	//get the nxt of T
    	nxt[1]=0; k=0;
    	for(j=2;j<=m;j++)
    	{
    		while(k && T[k+1]!=T[j])
    			k=nxt[k];
    		if(T[k+1]==T[j])
    			k++;
    		nxt[j]=k;
    	}
    	
    	//get preg,s
    	j=0;
    	tmp=0;
    	memset(s,0,sizeof(s));
    	for(i=1;i<=n;i++)
    	{
    		while(j && T[j+1]!=S[i])
    			j=nxt[j];
    		if(T[j+1]==S[i])
    			j++;
    		if(j==m)
    		{
    			tmp++;
    			j=nxt[j];
    		}
    		preg[i]=tmp; s[i][j]++;
    	}
    	for(i=2;i<=n;i++)
    		for(j=0;j<m;j++)
    			s[i][j]+=s[i-1][j];
    	for(i=2;i<=n;i++)
    		preg[i]+=preg[i-1];
    	
    	//get suf
    	for(i=0;i<m;i++)
    		for(j='a';j<='z';j++)
    		{
    			ismatch[i][j]=0;
    			k=i;
    			while(k!=0 && T[k+1]!=j)
    				k=nxt[k];
    			if(T[k+1]==j)
    				k++;
    			if(k==m)
    			{
    				ismatch[i][j]=1;
    				k=nxt[k];
    			}
    			nxt2[i][j]=k;
    		}
    	for(i=0;i<m;i++)
    		suf[n+1][i]=0;
    	for(i=n;i>=1;i--)
    		for(j=0;j<m;j++)
    			suf[i][j]=ismatch[j][S[i]]+suf[i+1][nxt2[j][S[i]]];
    	for(i=n;i>=1;i--)
    		for(j=0;j<m;j++)
    			suf[i][j]+=suf[i+1][j];
    }
    
    void solve()
    {
    	int i,j,L,R;
    	ll ans;
    	while(qur--)
    	{
    		scanf("%d%d",&L,&R);
    		ans=1ll*(n-R+1)*preg[L];
    		for(i=0;i<m;i++)
    			ans+=1ll*s[L][i]*suf[R][i];
    		printf("%lld
    ",ans);
    	}
    }
    
    int main()
    {
    	int i,j,cas;
    	scanf("%d",&cas);
    	while(cas--)
    	{
    		scanf("%d%d%d",&n,&m,&qur);
    		scanf("%s%s",S+1,T+1);
    		init();
    		solve();
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    loadrunner11 录制手机App
    http协议调试代理工具介绍
    Loadrunner无法打开IE浏览器问题总结
    loadrunner的安装及问题总结
    Mac常用快捷键
    迭代器
    生成器
    python小程序
    python练习
    python集合
  • 原文地址:https://www.cnblogs.com/FxxL/p/7291040.html
Copyright © 2011-2022 走看看