zoukankan      html  css  js  c++  java
  • [TJOI2019]甲苯先生和大中锋的字符串

    IV.[TJOI2019]甲苯先生和大中锋的字符串

    判断一个子串出现几次,我们仍然可以采取之前提到的遍历parent tree的方法。

    考虑一个等价类。明显,这个等价类中所有串都出现且仅出现了(等价类出现的次数)。若这个次数恰好为 \(k\),则从类中最长的串到最短的串,所有长度的串的数量都增加了 \(1\)。于是用一个差分数组维护这一过程,最后找到其中出现最多的长度即可。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int T,cnt,n,m;
    struct Suffix_Automaton{int ch[26],len,fa;}t[200100];
    int sz[200100];
    int Add(int x,int c){
    	int xx=++cnt;t[xx].len=t[x].len+1;
    	sz[xx]=1;
    	for(;x&&!t[x].ch[c];x=t[x].fa)t[x].ch[c]=xx;
    	if(!x){t[xx].fa=1;return xx;}
    	int y=t[x].ch[c];
    	if(t[y].len==t[x].len+1){t[xx].fa=y;return xx;}
    	int yy=++cnt;t[yy]=t[y];
    	t[yy].len=t[x].len+1;
    	t[y].fa=t[xx].fa=yy;
    	for(;x&&t[x].ch[c]==y;x=t[x].fa)t[x].ch[c]=yy;
    	return xx;
    }
    vector<int>v[200100];
    ll d[100100],mx;
    void dfs(int x){for(auto y:v[x])dfs(y),sz[x]+=sz[y];}
    char s[100100];
    int main(){
    	scanf("%d",&T);
    	while(T--){
    		scanf("%s%d",s,&m),n=strlen(s),cnt=1,mx=0;
    		for(int i=0,las=1;i<n;i++)las=Add(las,s[i]-'a');
    		for(int i=2;i<=cnt;i++)v[t[i].fa].push_back(i);
    		dfs(1);
    		for(int i=2;i<=cnt;i++)if(sz[i]==m)d[t[t[i].fa].len]--,d[t[i].len]++;
    		for(int i=n;i;i--)d[i]+=d[i+1],mx=max(mx,d[i]);
    		if(!mx)puts("-1");
    		else for(int i=n;i;i--)if(d[i]==mx){printf("%d\n",i);break;}
    		for(int i=1;i<=cnt;i++){memset(t[i].ch,0,sizeof(t[i].ch)),t[i].len=t[i].fa=sz[i]=0,v[i].clear();}
    		for(int i=1;i<=n;i++)d[i]=0;
    	}
    	return 0;
    } 
    

  • 相关阅读:
    Tomcat 三种运行方式
    MariaDB介绍
    Nginx 平滑升级
    代理命令 proxy_pass 详解
    Nginx 和 Tomcat 负载均衡
    基于Apache和tomcat实现负载均衡
    centos7 通过源码编译的方式安装和配置Apache
    基于nginx结合openssl实现https
    HTTP 和 HTTPS 区别
    linux系统中修改别名配置文件,构建命令别名
  • 原文地址:https://www.cnblogs.com/Troverld/p/14605673.html
Copyright © 2011-2022 走看看