• SP1812 LCS2


    Description:

    (n) 个长度 (le 10^5) 的字符串,求它们最长公共子串。(nle 10)

    Solution:

    把第一个字符串的 (SAM) 建出来,然后其他串在上跑,跑到一个点记录当前匹配的最长子串,但最后答案是和每个点匹配的最长中最小的去取 (min),所以在自动机上跑的时候维护一个 (lcs[x])(slcs[x]) 分别表示当前正在跑的串在这个节点匹配到的最长子串长度和之前所有的最小值,由于一个点匹配上了,它所有祖先都会匹配到,所以每跑完后每个点的 (lcs[x]) 要和它的儿子取 (max) 同时和自己的 (maxlen)(min) ,此时 (slcs) 再和 (lcs[x])(min) ,别忘记处理完一个串后要清空 (lcs[x])

    Code:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <fstream>
    
    typedef long long LL;
    typedef unsigned long long uLL;
    
    #define inline __inline__ __attribute__ ((always_inline)) 
    #define SZ(x) ((int)x.size())
    #define ALL(x) (x).begin(), (x).end()
    #define MP(x, y) std::make_pair(x, y)
    #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
    #define GO cerr << "GO" << endl;
    
    using namespace std;
    
    inline void proc_status()
    {
    	ifstream t("/proc/self/status");
    	cerr << string(istreambuf_iterator<char>(t), istreambuf_iterator<char>()) << endl;
    }
    
    template<class T> inline T read() 
    {
    	register int x = 0; register int f = 1; register char c;
    	while (!isdigit(c = getchar())) if (c == '-') f = -1;
    	while (x = (x << 1) + (x << 3) + (c xor 48), isdigit(c = getchar()));
    	return x * f;
    }
    
    template<typename T> inline bool chkmin(T &a, T b) { return a > b ? a = b, 1 : 0; }
    template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
    
    const int maxN = (int) 1e5;
    
    int len[12], n;
    int rk[maxN * 2], lcs[maxN * 2], slcs[maxN * 2];
    char str[12][maxN + 2];
    
    namespace SAM
    {
    	int Ncnt, last;
    
    	struct Status 
    	{ int len, link, ch[26]; } st[maxN * 2];
    
    	inline void init()
    	{ st[0].len = 0, st[0].link = -1, Ncnt = 0; }
    
    	inline void insert(char ch)
    	{
    		int c = ch - 'a';
    		int cur = ++Ncnt;
    		int p = last;
    		st[cur].len = st[last].len + 1;
    		while (p != -1 and !st[p].ch[c])
    		{
    			st[p].ch[c] = cur;
    			p = st[p].link;
    		}
    		if (p == -1)
    			st[cur].link = 0;
    		else 
    		{
    			int q = st[p].ch[c];
    			if (st[q].len == st[p].len + 1)
    				st[cur].link = q;
    			else 
    			{
    				int clone = ++Ncnt;
    				st[clone] = st[q];
    				st[clone].len = st[p].len + 1;
    				while (p != -1 and st[p].ch[c] == q)
    				{
    					st[p].ch[c] = clone;
    					p = st[p].link;
    				}
    				st[q].link = st[cur].link = clone;
    			}
    		}
    		last = cur;
    	}
    } 
    using namespace SAM;
    
    inline void Input()
    {
    	while (scanf("%s", str[++n] + 1) != EOF)
    		len[n] = strlen(str[n] + 1);
    	n--;
    }
    
    inline void Init()
    {
    	init();
    	for (register int i = 1; i <= len[1]; ++i)
    		insert(str[1][i]);
    
    	static int buc[maxN * 2];
    
    	for (register int i = 1; i <= Ncnt; ++i) buc[st[i].len]++;
    	for (register int i = 1; i <= Ncnt; ++i) buc[i] += buc[i - 1];
    	for (register int i = 1; i <= Ncnt; ++i) rk[buc[st[i].len]--] = i;
    
    	for (register int i = 0; i <= Ncnt; ++i) slcs[i] = (int) 1e5 + 1;
    }
    
    inline void Solve()
    {
    	for (int t = 2; t <= n; ++t)
    	{
    		for (register int i = 0; i <= Ncnt; ++i)
    			lcs[i] = 0;
    		int cur = 0, L = 0;
    		for (register int i = 1; i <= len[t]; ++i)
    		{
    			int c = str[t][i] - 'a';
    			while (cur != -1 and !st[cur].ch[c])
    			{
    				cur = st[cur].link;
    				if (cur != -1)
    					L = st[cur].len;
    			}
    			if (cur == -1)
    				cur = 0;
    			else 
    			{
    				L++;
    				cur = st[cur].ch[c];
    				chkmax(lcs[cur], L);
    			}
    		}
    		for (register int i = Ncnt; i >= 1; --i)
    		{
    			int cur = rk[i];
    			chkmin(lcs[cur], st[cur].len);
    			chkmin(slcs[cur], lcs[cur]);
    			if (cur) chkmax(lcs[st[cur].link], lcs[cur]);
    		}
    	}
    	int ans = 0;
    	for (register int i = 1; i <= Ncnt; ++i)
    		chkmax(ans, slcs[i]);
    	cout << ans << '
    ';
    }
    
    int main() 
    {
    #ifndef ONLINE_JUDGE
    	freopen("xhc.in", "r", stdin);
    	freopen("xhc.out", "w", stdout);
    #endif
    
    	Input();
    
    	Init();
    
    	Solve();
    
    	return 0;
    }
    
  • 相关阅读:
    2017.6.30 码云--生成公钥
    2017.6.30 IDEA插件--gsonfomat的安装与使用
    2017.6.30 安装IDEA的插件mybatis plugin(破解版)
    2017.6.29 java读取.properties配置文件的几种方法
    2017.6.29 移除再导入maven module到IDEA中时提示: Unable to proceed. Nothing found to import.
    2017.6.27 跟开涛学spring3--spring概述
    2017.6.27 jdbc基本使用
    2017.6.26 接口测试工具postman使用总结
    16-20
    11-15
  • 原文地址:https://www.cnblogs.com/cnyali-Tea/p/11481866.html
Copyright © 2020-2023  润新知