• 【SPOJ】1812. Longest Common Substring II(后缀自动机)


    http://www.spoj.com/problems/LCS2/

    发现了我原来对sam的理解的一个坑233

    本题容易看出就是将所有匹配长度记录在状态上然后取min后再对所有状态取max。

    但是不要忘记了一点:更新parent树的祖先。

    为什么呢?首先如果子树被匹配过了,那么长度一定大于任意祖先匹配的长度(甚至有些祖先匹配长度为0!为什么呢,因为我们在匹配的过程中,只是找到一个子串,可能还遗漏了祖先没有匹配到,这样导致了祖先的记录值为0,那么在对对应状态取min的时候会取到0,这样就wa了。而且注意,如果匹配到了当前节点,那么祖先们一定都可以赋值为祖先的length!因为当前节点的length大于任意祖先。(

    比如数据

    acbbc
    bc
    ac

    答案应该是1没错吧。如果没有更新祖先,那么答案会成0。

    这个多想想就行了。

    所以以后记住:对任意多串匹配时,凡是对同一个状态取值时,要注意当前状态的子树是否比当前状态记录的值优。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <set>
    #include <map>
    using namespace std;
    typedef long long ll;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define error(x) (!(x)?puts("error"):0)
    #define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    
    struct sam {
    	static const int N=250005;
    	int c[N][26], l[N], f[N], root, last, cnt, mx[N], x[N];
    	sam() { cnt=0; root=last=++cnt; }
    	void add(int x) {
    		int now=last, a=++cnt; last=a;
    		l[a]=l[now]+1;
    		for(; now && !c[now][x]; now=f[now]) c[now][x]=a;
    		if(!now) f[a]=root;
    		else {
    			int q=c[now][x];
    			if(l[q]==l[now]+1) f[a]=q;
    			else {
    				int b=++cnt;
    				memcpy(c[b], c[q], sizeof c[q]);
    				l[b]=l[now]+1;
    				f[b]=f[q];
    				f[q]=f[a]=b;
    				for(; now && c[now][x]==q; now=f[now]) c[now][x]=b;
    			}
    		}
    	}
    	void build(char *s) {
    		int len=strlen(s);
    		rep(i, len) add(s[i]-'a');
    		for1(i, 1, cnt) mx[l[i]]++;
    		for1(i, 1, len) mx[i]+=mx[i-1];
    		for1(i, 1, cnt) x[mx[l[i]]--]=i;
    		for1(i, 1, cnt) mx[i]=l[i];
    	}
    	void find(char *s) {
    		int now=root, t=0, len=strlen(s);
    		static int arr[N];
    		rep(i, len) {
    			int k=s[i]-'a';
    			if(c[now][k]) ++t, now=c[now][k];
    			else {
    				while(now && !c[now][k]) now=f[now];
    				if(!now) t=0, now=root;
    				else t=l[now]+1, now=c[now][k];
    			}
    			arr[now]=max(arr[now], t);
    		}
    		for3(i, cnt, 1) {
    			t=x[i];
    			mx[t]=min(mx[t], arr[t]);
    			if(arr[t] && f[t]) arr[f[t]]=l[f[t]];
    			arr[t]=0;
    		}
    	}
    	int getans() {
    		int ret=0;
    		for1(i, 1, cnt) ret=max(ret, mx[i]);
    		return ret;
    	}
    }a;
    
    const int N=100005;
    char s[N];
    int main() {
    	scanf("%s", s);
    	a.build(s);
    	while(~scanf("%s", s)) a.find(s);
    	print(a.getans());
    	return 0;
    }
    

      


    A string is finite sequence of characters over a non-empty finite set Σ.

    In this problem, Σ is the set of lowercase letters.

    Substring, also called factor, is a consecutive sequence of characters occurrences at least once in a string.

    Now your task is a bit harder, for some given strings, find the length of the longest common substring of them.

    Here common substring means a substring of two or more strings.

    Input

    The input contains at most 10 lines, each line consists of no more than 100000 lowercase letters, representing a string.

    Output

    The length of the longest common substring. If such string doesn't exist, print "0" instead.

    Example

    Input:
    alsdfkjfjkdsal
    fdjskalajfkdsla
    aaaajfaaaa
    
    Output:
    2
    

    Notice: new testcases added

  • 相关阅读:
    这次面试就差不多了,你有什么问题需要问我呢?
    C++为啥要使用new
    C#读取“我的文档”等特殊系统路径及环境变量
    C++11 Lambda表达汇总总结
    c#计算 坐标点与坐标点之间的距离
    eclipse svn同步资源库时忽略某些不需要提交文件类型和文件夹
    通俗理解TCP/IP协议三次握手四次分手流程
    mysql 免安装版 启动服务马上关闭
    MySQL数据库安装与配置详解
    word 插入的图片被嵌套在文字底下
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4145712.html
Copyright © 2020-2023  润新知