- 1、本文档共4页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
解题思路
首先我们得分析操作的本质,我们发现每次操作都是把字符串的某一个前缀移动到后缀后面拼起来。
由于:pre(i)=s1s2....si,suf(i+1)=si+1si+2....sn。
我们发现?suf(i+1)+pre(i)=si+1si+2....sns1s2....si。
这个过程其实是可以看成s1,s2,...,si?这几个字符依次进行右移到字符串末尾,故我们发现了这一的操作本质是在将一些字符进行循环右移操作,即任意一个操作,我们都可以找到一种字符的循环右移方式对应起来。
那么在操作过程中,由于每次操作和循环右移是对应的,故我们的操作过程就是不断的把这个字符串的第一个字符
循环右移,所以其实我们发现他最多就只能产生?n?种字符串,因为第一个字符循环右移?nn?次之后又会变成原先的字符串?S。那么由于小蓝的操作次数是?10^1000,这个数是非常大的,远远大于字符串的长度?n,故我们发现这一的操作一定可以产生所有能产生的不同字符串。
故问题转化为了,给定一个字符串?S?,通过不断的循环右移,可以形成多少种不同的字符串?
故我们需要判断:
S=s1s2...sn
S=s2...sns1
S=s3...sns1s2
.......
S=sns1s2...sn?1
到底有几种不同的字符串。
由于?n≤106?,直接采用暴力判断的复杂度为O(n2),显然是不可接受的,那么我们可以采用字符串哈希。
这里简单介绍字符串哈希的基本步骤:
选择一个适当的进制数,通常取质数,例如?p。
将字符串视为一个多项式,将每个字符转换为对应的数值,可以使用ASCII码减去a或A得到不同的数值表示。
计算多项式的哈希值,通过对每个字符的数值乘以进制的幂次方并相加得到。例如,对于字符串ABC,哈希值可以计算为h=(A×p2+B×p1+C×p0)modM,其中?M?是一个大于字符串长度的数值,用于防止哈希值溢出。
对于比较字符串是否相等的问题,只需比较它们的哈希值是否相等即可。
需要注意的是,选择适当的进制数?p?和模数?M?对于哈希算法的效果至关重要。一般来说,选择一个较大的质数作为进制数和模数可以减少哈希冲突的可能性,提高哈希算法的准确性。
这里我们可以采用自然溢出的哈希方法,即把哈希值的类型定义成?unsignedlonglong,这样溢出它会自动向?2^64?取模,我们可以不用额外选取模数了,我们只要选取一个合适的进制数即可,我们这选取?p=131p=131。
这里的做法是:枚举?ii,每次利用字符串哈希将s1s2…si?拼接到?si+1si+2…sn?的末尾。
我们可以预处理两个数组:h[i],p[i],其中?h[i]?表示字符串前缀?ii?的哈希值,p[i]?表示进制数的?i?次方,那么我们根据这两个数组,预处理出前缀的哈希值,并利用前缀和的思想重新计算新字符串的哈希值。
每次枚举?ii,我们可以得到将?s_1s_2\dotss_is1s2…si?拼接到?s_{i+1}s_{i+2}\dotss_nsi+1si+2…sn?的末尾形成的新字符串的哈希值的式子:Hash=(h[n]-h[i]*p[n-i])*p[i]+h[i]Hash=(h[n]?h[i]?p[n?i])?p[i]+h[i]然后将这些得到不同的?HashHash?值丢到一个?unordered_set?里面自动去重,这样我们就可以有效的统计不同的字符串数量了。
AC_Code
C++
#includebits/stdc++.h
usingnamespacestd;
typedefunsignedlonglongULL;
constintN=1e6+10;
ULLh[N],p[N],b=131;
intmain(){
cin.tie(nullptr)-ios::sync_with_stdio(false);
intn;
cinn;
strings;
cins;
s=?+s;
p[0]=1;
for(inti=1;i=n;i++){
p[i]=p[i-1]*b;
h[i]=h[i-1]*b+s[i];
}
unordered_setULLse;
for(inti=1;i=n;i++){
ULLhash=(h[n]-h[i]*p[n-i])*p[i]+h[i];
se.insert(hash);
}
文档评论(0)