• 【LOJ】#2123. 「HEOI2015」最短不公共子串


    题解

    我们对于B串建出后缀自动机和序列自动机
    对于问题1,枚举左端点然后跑后缀自动机,直到不能匹配作为这个左端点的答案
    对于问题2,枚举左端点然后跑序列自动机,直到不能匹配

    对于问题3,设f[i][j]表示第前i个字符匹配到后缀自动机上第j个点的最少步数,如果下一步走不了则更新答案
    对于问题4,设f[i][j]表示前i个字符匹配到序列自动机上第j个点的最少步数,如果下一步走不了则更新答案

    代码

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #define enter putchar('
    ')
    #define space putchar(' ')
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    template<class T>
    void read(T &res) {
    	res = 0;char c = getchar();T f = 1;
    	while(c < '0' || c > '9') {
    		if(c == '-') f = -1;
    		c = getchar();
    	}
    	while(c >= '0' && c <= '9') {
    		res = res * 10 + c - '0';
    		c = getchar();
    	}
    	res *= f;
    }
    template<class T>
    void out(T x) {
    	if(x < 0) {putchar('-');x = -x;}
    	if(x >= 10) {
    		out(x / 10);
    	}
    	putchar('0' + x % 10);
    }
    const int MOD = 1000000007;
    char A[2005],B[2005];
    int LA,LB;
    int f[2005][4005];
    struct SuffixAutoMaton{
    	struct SAM_node {
    		SAM_node *par,*nxt[26];
    		int len;
    		SAM_node *find_next(char c) {
    			if(nxt[c - 'a']) return nxt[c - 'a'];
    			else return NULL;
    		}
    	}pool[4005],*tail = pool,*root,*last;
    	SuffixAutoMaton() {
    		root = last = tail++;
    	}
    	void build(int l,int e) {
    		SAM_node *nowp = tail++,*p;
    		nowp->len = l;
    		for(p = last ; p && !p->nxt[e]; p = p->par) {
    			p->nxt[e] = nowp;
    		}
    		if(!p) nowp->par = root;
    		else {
    			SAM_node *q = p->nxt[e];
    			if(q->len == p->len + 1) nowp->par = q;
    			else {
    				SAM_node *copyq = tail++;
    				*copyq = *q;
    				copyq->len = p->len + 1;
    				q->par = nowp->par = copyq;
    				for( ; p && p->nxt[e] == q ; p = p->par) {
    					p->nxt[e] = copyq;
    				}
    			}
    		}
    		last = nowp;
    	}
    	int calc1(int st) {
    		SAM_node *p = root;
    		int res = 0;
    		for(int i = st ; i <= LA ; ++i) {
    			p = p->find_next(A[i]);
    			if(!p) break;
    			++res;
    		}
    		if(res == LA - st + 1) return LA + 1;
    		return res + 1;
    	}
    	int calc3() {
    		int m = tail - pool;
    		for(int i = 0 ; i <= LA ; ++i) {
    			for(int j = 1 ; j <= m ; ++j) {
    				f[i][j] = 0x7fffffff;
    			}
    		}
    		f[0][1] = 0;
    		int res = LA + 1;
    		for(int i = 1 ; i <= LA ; ++i) {
    			for(int j = 1 ; j <= m ; ++j) {
    				if(f[i - 1][j] != 0x7fffffff) {
    					f[i][j] = min(f[i - 1][j],f[i][j]);
    					SAM_node *p = pool[j - 1].find_next(A[i]);
    					if(!p) res = min(res,f[i - 1][j] + 1);
    					else f[i][p - pool + 1]  = min(f[i][p - pool + 1],f[i][j] + 1);
    				}
    			}
    		}
    		return res;
    	}
    }SAM;
    struct LineAutoMaton {
    	int ch[2005][26],head[30],next[2005],tot,rt;
    	LineAutoMaton() {
    		rt = tot = 1;
    		for(int i = 0 ; i < 26 ; ++i) head[i] = 1;
    	}
    	void build(char c) {
    		++tot;next[tot] = head[c - 'a'];
    		for(int i = 0 ; i < 26 ; ++i) {
    			for(int j = head[i] ; j ; j = next[j]) {
    				if(!ch[j][c - 'a']) ch[j][c - 'a'] = tot;
    				else break;
    			}
    		}
    		head[c - 'a'] = tot;
    	}
    	int calc2(int st) {
    		int p = rt,L = 0;
    		for(int i = st ; i <= LA ; ++i) {
    			if(ch[p][A[i] - 'a']) {
    				p = ch[p][A[i] - 'a'];
    				++L;
    			}
    			else break;
    		}
    		if(L == LA - st + 1) return LA + 1;
    		return L + 1;
    	}
    	int calc4() {
    		for(int i = 0 ;i <= LA ; ++i) {
    			for(int j = 1 ; j <= tot ; ++j) {
    				f[i][j] = 0x7fffffff;
    			}
    		}
    		f[0][1] = 0;
    		int res = LA + 1;
    		for(int i = 1 ; i <= LA ; ++i) {
    			for(int j = 1 ; j <= tot ; ++j) {
    				if(f[i - 1][j] != 0x7fffffff) {
    					f[i][j] = min(f[i - 1][j],f[i][j]);
    					int p = ch[j][A[i] - 'a'];
    					if(!p) res = min(res,f[i - 1][j] + 1);
    					else f[i][p] = min(f[i - 1][j] + 1,f[i][p]); 
    				}
    			}
    		}
    		return res;
    	}	
    }LAM;
    void Init() {
    	scanf("%s",A + 1);
    	scanf("%s",B + 1);
    	LA = strlen(A + 1);LB = strlen(B + 1);
    	for(int i = 1 ; i <= LB ; ++i) {
    		SAM.build(i,B[i] - 'a');
    		LAM.build(B[i]);
    	}
    }
    void Solve1() {
    	int ans = LA + 1;
    	for(int i = 1 ; i <= LA ; ++i) {
    		ans = min(ans,SAM.calc1(i));
    	}
    	if(ans > LA) puts("-1");
    	else {out(ans),enter;}
    }
    void Solve2() {
    	int ans = LA + 1;
    	for(int i = 1 ; i <= LA ; ++i) {
    		ans = min(ans,LAM.calc2(i));
    	}
    	if(ans > LA) puts("-1");
    	else out(ans),enter;
    }
    void Solve3() {
    	int ans = SAM.calc3();
    	if(ans > LA) puts("-1");
    	else out(ans),enter;
    }
    void Solve4() {
    	int ans = LAM.calc4();
    	if(ans > LA) puts("-1");
    	else out(ans),enter;
    }
    int main() {
    #ifdef ivorysi
    	freopen("f1.in","r",stdin);
    #endif
    	Init();
    	Solve1();
    	Solve2();
    	Solve3();
    	Solve4();
    }
    
  • 相关阅读:
    python2代码改成python3踩过的坑
    Mac下为什么有的文件名后带一个* 星号?
    Mac 的 Vim 中 delete 键失效的原因和解决方案(转)
    使用pandas处理大型CSV文件(转)
    Java基础——02
    javaee相关基础
    Cookie&Session笔记
    EL&JSTL笔记------jsp
    JavaWeb基础
    Java基础——01
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9188942.html
Copyright © 2020-2023  润新知