ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

hdu4622(hash解法)

2019-04-24 22:41:03  阅读:279  来源: 互联网

标签:ch hash int ll hdu4622 ull maxn include 解法


题目链接: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\n",dp[l][r]);
		}
	}
	return 0;
}

  使用map判重:

 

建图判重:

 (区别太大了吧QAQ)

标签:ch,hash,int,ll,hdu4622,ull,maxn,include,解法
来源: https://www.cnblogs.com/Zhi-71/p/10765449.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有