[arc077f]SS
来源:互联网 发布:exe打包软件 编辑:程序博客网 时间:2024/05/22 15:57
前言
有趣的字符串题。
我是不是推出了什么和大家看起来不一样实质上一样的东西。
题目大意
定义AA表示两个一样的字符串A接在一起。
定义F(SS)=TT,TT是长度最小的满足条件的字符串且SS是TT的前缀。
给你小写字母串SS,求
有趣
这显然是一道和border相关的题。
然后可以发现只考虑S的变化就行,不需要考虑SS。
先做一遍kmp求出nxt(S)。
我们不妨分类讨论一下。
如果S本身就是一个循环串,容易发现F了10^100次后就是这个循环节无限循环,只需要统计一个循环节内每个字母出现次数即可,最后剩余一点再去统计对应前缀。
如果不是循环串呢?
有一个结论是它永远不会变成循环串。
如果
那么不妨只讨论
一次变换后会变成ABAAB,nxt变成AB(可以用反证法证明不会更长,否则原串是循环串),假如设cnt1表示A中某字母出现次数,cnt2表示B中某字母出现次数。
那么一次变换|S’|=2*|S|-nxt(S),nxt(S’)=|S|-nxt(S),cnt1’=cnt1+cnt2,cnt2’=cnt1。
于是可以注意到
可以参考代码实现。
#include<cstdio>#include<algorithm>#include<cstring>#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--)using namespace std;typedef long long ll;const int maxn=200000+10;const ll inf=1000000000000000000;char s[maxn];ll len[1000],nt[1000],cnt1[1000][27],cnt2[1000][27],o[27],ans[27];int nxt[maxn];int i,j,k,t,n,m,tot,top;ll l,r;void kmp(){ j=0; fo(i,2,n){ while (j&&s[j+1]!=s[i]) j=nxt[j]; if (s[j+1]==s[i]) j++; nxt[i]=j; }}void work(ll n,int f){ int i,j; fd(i,top,1) if (n>=len[i]){ fo(j,0,25) ans[j]+=f*(cnt1[i][j]*2+cnt2[i][j]); n-=len[i]; } if (n>=len[0]){ fo(j,0,25) ans[j]+=f*o[j]; n-=len[0]; } fo(i,1,n) ans[s[i]-'a']+=f;}void solve(ll n,int f){ int i,j; fo(i,0,25) ans[i]+=(ll)f*(n/tot)*o[i]; n%=tot; fo(i,1,n) ans[s[i]-'a']+=f;}int main(){ scanf("%s",s+1); n=strlen(s+1); n/=2; kmp(); if (n%(n-nxt[n])){ fo(i,1,nxt[n]) cnt1[0][s[i]-'a']++; fo(i,nxt[n]+1,n-nxt[n]) cnt2[0][s[i]-'a']++; fo(i,1,n) o[s[i]-'a']++; len[0]=n;nt[0]=nxt[n]; if (nxt[n]>=(n+1)/2){ top++; len[top]=len[top-1]*2-nt[top-1]; nt[top]=len[top-1]-nt[top-1]; fo(i,1,nt[top]) cnt1[top][s[i]-'a']++; fo(i,n-nxt[n]+1,n) cnt2[top][s[i]-'a']++; } while (len[top]<inf){ top++; len[top]=len[top-1]*2-nt[top-1]; nt[top]=len[top-1]-nt[top-1]; fo(i,0,25){ cnt1[top][i]=cnt1[top-1][i]+cnt2[top-1][i]; cnt2[top][i]=cnt1[top-1][i]; } } scanf("%lld%lld",&l,&r); work(r,1); work(l-1,-1); fo(i,0,25) printf("%lld ",ans[i]); } else{ tot=n-nxt[n]; fo(i,1,tot) o[s[i]-'a']++; scanf("%lld%lld",&l,&r); solve(r,1); solve(l-1,-1); fo(i,0,25) printf("%lld ",ans[i]); }}
- [arc077f]SS
- ss
- ss
- ss
- ss
- ss
- ss
- ss
- ss
- ss
- ss
- ss
- ss
- ss
- ss
- ss
- ss
- ss
- Unity ScrollView图片滑动翻页效果
- 用Java实现冒泡排序法
- 看图说话排序算法之归并排序
- Fibonacci Again HDU
- CentOS 7.3 安装redis 4.0.2服务
- [arc077f]SS
- 构造函数
- UI 控件 -> ChoiceBox
- String类简单实现
- SequenceInputStream多文件复制器
- 当面付DEMO .net 开发过程 开放平台密钥配置说明
- 校验和算法分析【转】
- Spring 5.0 bean的自动装配 02
- poj1426 Find The Multiple(bfs)