zoukankan      html  css  js  c++  java
  • 【SP1811】LCS

    【SP1811】LCS - Longest Common Substring

    题面

    洛谷

    题解

    建好后缀自动机后从初始状态沿着现在的边匹配,

    如果失配则跳它的后缀链接,因为你跳后缀链接到达的(Endpos)集合中的串肯定是当前(Endpos)中的后缀,所以这么做是对的。

    你感性理解一下,这样显然是最大的是吧。。。

    具体实现看代码:

    代码

    #include <iostream> 
    #include <cstdio> 
    #include <cstdlib> 
    #include <cstring> 
    #include <cmath> 
    #include <algorithm> 
    using namespace std; 
    const int MAX_N = 2.5e5 + 5; 
    struct Node { int ch[26], fa, len; } t[MAX_N << 1]; 
    int lst = 1, tot = 1; 
    void extend(int c) { 
    	++tot, t[lst].ch[c] = tot; 
    	t[tot].len = t[lst].len + 1; 
    	int p = t[lst].fa; lst = tot; 
    	while (p && !t[p].ch[c]) t[p].ch[c] = tot, p = t[p].fa; 
    	if (!p) return (void)(t[tot].fa = 1); 
    	int q = t[p].ch[c]; 
    	if (t[q].len == t[p].len + 1) return (void)(t[tot].fa = q); 
    	int _q = ++tot; 
    	t[_q] = t[q], t[q].fa = t[tot - 1].fa = _q; 
    	t[_q].len = t[p].len + 1; 
    	while (p && t[p].ch[c] == q) t[p].ch[c] = _q, p = t[p].fa; 
    } 
    char s1[MAX_N], s2[MAX_N]; 
    int N; 
    int main () {
    #ifndef ONLINE_JUDGE 
        freopen("cpp.in", "r", stdin);
    #endif
    	scanf("%s%s", s1 + 1, s2 + 1); 
    	N = strlen(s1 + 1); 
    	for (int i = 1; i <= N; i++) extend(s1[i] - 'a'); 
    	N = strlen(s2 + 1); 
    	int ans = 0, l = 0, v = 1; 
    	for (int i = 1; i <= N; i++) {
    		while (v && !t[v].ch[s2[i] - 'a']) v = t[v].fa, l = t[v].len; 
    		if (!v) v = 1, l = 0; 
    		if (t[v].ch[s2[i] - 'a']) v = t[v].ch[s2[i] - 'a'], ++l;
    		ans = max(ans, l); 
    	} 
    	printf("%d
    ", ans); 
        return 0; 
    } 
    
  • 相关阅读:
    二分和牛顿法实现开根号
    leetcode 44. 通配符匹配
    leetcode 91. 解码方法
    leetcode 236. 二叉树的最近公共祖先
    leetcode 39. 组合总数
    leetcode:146. LRU缓存机制
    leetcode:124. 二叉树中的最大路径和
    二叉树前序遍历,中序遍历,后序遍历以及层次遍历实现
    leetcode: 4. 寻找两个有序数组的中位数
    Leetcode: 43. 接雨水
  • 原文地址:https://www.cnblogs.com/heyujun/p/10597179.html
Copyright © 2011-2022 走看看