zoukankan      html  css  js  c++  java
  • UVA12206 Stammering Aliens 【SAM 或 二分 + hash】

    题意

    求一个串中出现至少m次的子串的最大长度,对于最大长度,求出最大的左端点

    题解

    本来想练哈希的,没忍住就写了一个SAM
    SAM拿来做就很裸了
    只要检查每个节点的right集合大小是否不小于m,然后step[u]就表示u节点所代表字符串的最大长度
    为了求出端点,我们还需要记录right集合的最大值
    然后就水过啦

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define LL long long int
    #define Redge(u) for (int k = h[u]; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define ULL unsigned long long int
    #define cls(s) memset(s,0,sizeof(s))
    using namespace std;
    const int maxn = 80005,maxm = 100005,INF = 1000000000;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    char s[maxn];
    int m,n,b[maxn],a[maxn],ans,ansr;
    int ch[maxn][26],pre[maxn],sz[maxn],l[maxn],r[maxn],last,cnt;
    void init(){
    	cls(ch); cls(pre); cls(sz); cls(l); cls(r); last = cnt = 1; ans = 0;
    }
    void ins(int x){
    	int p = last,np = ++cnt; last = np;
    	r[np] = l[np] = l[p] + 1; sz[np] = 1;
    	while (p && !ch[p][x]) ch[p][x] = np,p = pre[p];
    	if (!p) pre[np] = 1;
    	else {
    		int q = ch[p][x];
    		if (l[q] == l[p] + 1) pre[np] = q;
    		else {
    			int nq = ++cnt;
    			l[nq] = l[p] + 1;
    			for (int i = 0; i < 26; i++) ch[nq][i] = ch[q][i];
    			pre[nq] = pre[q]; pre[q] = pre[np] = nq;
    			while (ch[p][x] == q) ch[p][x] = nq,p = pre[p];
    		}
    	}
    }
    void build(){
    	for (int i = 1; i <= n; i++) ins(s[i] - 'a');
    	for (int i = 0; i <= cnt; i++) b[i] = 0;
    	for (int i = 1; i <= cnt; i++) b[l[i]]++;
    	for (int i = 1; i <= cnt; i++) b[i] += b[i - 1];
    	for (int i = 1; i <= cnt; i++) a[b[l[i]]--] = i;
    }
    void solve(){
    	for (int i = cnt; i; i--){
    		int u = a[i];
    		sz[pre[u]] += sz[u];
    		r[pre[u]] = max(r[pre[u]],r[u]);
    		if (u != 1 && sz[u] >= m){
    			if (l[u] > ans) ans = l[u],ansr = r[u] - l[u];
    			else if (l[u] == ans && r[u] - l[u] > ansr) ansr = r[u] - l[u];
    		}
    	}
    }
    int main(){
    	while (m = read()){
    		init();
    		scanf("%s",s + 1); n = strlen(s + 1);
    		build();
    		solve();
    		if (ans) printf("%d %d
    ",ans,ansr);
    		else puts("none");
    	}
    	return 0;
    }
    
    

    二分 + hash的乱搞也写写

  • 相关阅读:
    ps photoshop cc 2015 Extract Assets(生成器)切图大法
    获取免费代理推荐
    nodejs http代理请求
    nodejs 发起http请求
    AHK GUI开发示例
    为【桌面右键菜单
    NPM 模块收集
    nodejs Commander 命令行神器简单示例
    如何用nodejs 开发一个命令行交互工具
    利用 T-sql 的从句 for xml path('') 实现多行合并到一行, 并带有分隔符
  • 原文地址:https://www.cnblogs.com/Mychael/p/8504553.html
Copyright © 2011-2022 走看看