zoukankan      html  css  js  c++  java
  • hdu4622(hash解法)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4622

    Now you are back,and have a task to do:
    Given you a string s consist of lower-case English letters only,denote f(s) as the number of distinct sub-string of s.
    And you have some query,each time you should calculate f(s[l...r]), s[l...r] means the sub-string of s start from l end at r.

     
    Input
    The first line contains integer T(1<=T<=5), denote the number of the test cases.
    For each test cases,the first line contains a string s(1 <= length of s <= 2000).
    Denote the length of s by n.
    The second line contains an integer Q(1 <= Q <= 10000),denote the number of queries.
    Then Q lines follows,each lines contains two integer l, r(1 <= l <= r <= n), denote a query.
     
    Output
    For each test cases,for each query,print the answer in one line.
     
    Sample Input
    2
    bbaba
    5
    3 4
    2 2
    2 5
    2 4
    1 4
    baaba
    5
    3 3
    3 4
    1 4
    3 5
    5 5
     
    Sample Output
    3
    1
    7
    5
    8
    1
    3
    8
    5
    1
    Hint
    I won't do anything against hash because I am nice.Of course this problem has a solution that don't rely on hash.
    题意:查询区间【l,r】的字符串有多少种不同的字串。
    解法:这题也可以用后缀自动机解,这里只简单讲一下hash的做法。
    首先我们可以枚举区间的长度L,然后枚举区间的起点l。然后我们可以考虑去重的情况,举个栗子吧:比如某字符串为abcabc,我们可以发现abc在区间【1,6】中出现了两次,所以我们应该减掉一个。去重的话,可以利用hash判断当前字符串之前是否出现过,那么问题来了:如果我们定义一个map<ull,int>,来判断的话,可能会出现超时的情况(目前还不知道为啥,难道是使用map的原因吗),做到这里我们可以建一个图,图的边权值为此时字符串的hash值,具体的实现看代码中的注释吧。
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #include<stack>
    #include<cstdio>
    #include<map>
    #include<set>
    #include<string>
    #include<queue>
    using namespace std;
    #define inf 0x3f3f3f3f
    #define ri register int
    typedef long long ll;
    typedef unsigned long long ull;
    
    inline ll gcd(ll i,ll j){
    	return j==0?i:gcd(j,i%j);
    }
    inline ll lcm(ll i,ll j){
    	return i/gcd(i,j)*j;
    }
    inline void output(int x){
    	if(x==0){putchar(48);return;}
    	int len=0,dg[20];
    	while(x>0){dg[++len]=x%10;x/=10;}
    	for(int i=len;i>=1;i--)putchar(dg[i]+48);
    }
    inline void read(int &x){
        char ch=x=0;
        int f=1;
        while(!isdigit(ch)){
        	ch=getchar();
    		if(ch=='-'){
    			f=-1;
    		}	
    	}
        while(isdigit(ch))
            x=x*10+ch-'0',ch=getchar();
            x=x*f;
    }
    
    const ull p=131;
    const int maxn=2e3+5;
    ull bit[maxn];
    char ch[maxn];ull ha[maxn];
    const ull mod=1e5+7;
    ull getha(int l,int r){
    	if(l==r)return ch[l];
    	return ha[r]-ha[l-1]*bit[r-l+1];
    }
    struct gra{
    	int head[mod+5];
    	int pos[maxn];//当前字符出现的最晚的位置 
    	int next[maxn];
    	ull edg[maxn];//hash值 
    	int num;
    	void init(){
    		num=0;
    		memset(head,0,sizeof(head));
    	}
    	int find(ull val,int id){
    		int u=val%mod;
    		for(int i=head[u];i!=0;i=next[i]){
    			if(edg[i]==val){
    				int tem=pos[i];
    				pos[i]=id;
    				return tem;
    			}
    		}
    		num++;
    		edg[num]=val;
    		pos[num]=id;
    		next[num]=head[u];
    		head[u]=num;
    		return 0;
    	}
    }h;
    int dp[maxn][maxn];
    int main(){
    	int t,q,l,r;
    	scanf("%d",&t);
    	bit[0]=1;
    	for(int i=1;i<maxn;i++){
    		bit[i]=bit[i-1]*p;
    	}
    	while(t--){
    		scanf("%s",ch+1);
    		int len=strlen(ch+1);
    		memset(dp,0,sizeof(dp));
    		ha[0]=1;
    		for(int i=1;i<=len;i++){
    			ha[i]=ha[i-1]*p+ch[i];
    		}
    		for(int i=1;i<=len;i++){
    			h.init();
    			for(int lm=1;lm+i-1<=len;lm++){
    				ull tem=getha(lm,lm+i-1);
    				int pos=h.find(tem,lm);
    				dp[pos][lm+i-1]--;
    				dp[lm][lm+i-1]++;
    			}
    		}
    		for(int i=len;i>=1;i--){
    			for(int j=i+1;j<=len;j++){
    				dp[i][j]+=dp[i][j-1]+dp[i+1][j]-dp[i+1][j-1];
    			}
    		}
    		scanf("%d",&q);
    		while(q--){
    			scanf("%d%d",&l,&r);
    			printf("%d
    ",dp[l][r]);
    		}
    	}
    	return 0;
    }
    

      使用map判重:

    建图判重:

     (区别太大了吧QAQ)

  • 相关阅读:
    kaldi的TIMIT实例二
    kaldi的TIMIT实例一
    kaldi脚本注释二
    kaldi脚本注释一
    [转]kaldi特征和模型空间转换
    [转]kaldi中的特征提取
    [转]kaldi上的深度神经网络
    [转]语音识别中区分性训练(Discriminative Training)和最大似然估计(ML)的区别
    [转]kaldi中的在线识别----Online Recognizers
    [转]决策树在Kaldi中如何使用
  • 原文地址:https://www.cnblogs.com/Zhi-71/p/10765449.html
Copyright © 2011-2022 走看看