【LOJ】#2172. 「FJOI2016」全部公共子序列問題

題解

據說是什麼序列自動機? 咱們考慮對於每一個位置的串,下面拼接相同的字符時,拼接最近的一個,這樣能夠保證不重不漏 爲了實現這個咱們須要什麼呢,咱們須要一個鏈表,記錄一下每一個位置的下一個字符會轉移到哪裏 例如 ABAB ch[1]['A'] = 3 ch[1]['B'] = 2 聽起來挺好建的,具體能夠看代碼ios

而後咱們記錄dp[a][b]是第一個字符串a位置的字符爲開頭,第二個字符串b位置的字符爲開頭,公共子序列的個數 能夠記憶化搜索,每一次枚舉下一個位置拼接上哪一個字符 輸出方案的話也是同樣,枚舉下一個位置拼上哪一個字符this

後五個點須要高精度啊= =spa

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <map>
//#define ivorysi
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define mo 974711
#define MAXN 3055
#define RG register
using namespace std;
typedef long long int64;
typedef double db;
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);
}
int N,M,MK,ci[205];
char x[MAXN],y[MAXN],ic[205],s[MAXN];
struct segAM {
	int head[62],next[MAXN],ch[MAXN][62],tot;
	segAM() {
		tot = 1;next[1] = 0;
		for(int i = 0 ; i <= 60; ++i) head[i] = 1;
	}
	void Insert(char c) {
		++tot;
		next[tot] = head[ci[c]];
		for(int i = 0 ; i <= 51 ; ++i) {
			for(int j = head[i] ; j && !ch[j][ci[c]] ; j = next[j]) {
				ch[j][ci[c]] = tot;
			}
		}
		head[ci[c]] = tot;
	}
}S1,S2;
const int BASE = 100000000;
const int LEN = 8;
struct Bignum {
	vector<int> v;
	Bignum operator = (int64 x) {
		v.clear();
		do {
			v.pb(x % BASE);
			x /= BASE;
		}while(x);
		return *this;
	}
	friend Bignum operator + (const Bignum &a,const Bignum &b) {
		Bignum c;c.v.clear();
		int p = 0,g = 0;
		while(1) {
			int x = g;
			if(p < a.v.size()) x += a.v[p];
			if(p < b.v.size()) x += b.v[p];
			++p;
			if(!x) break;
			c.v.pb(x % BASE);
			g = x / BASE;
		}
		return c;
	}
	void print() {
		int s = v.size() - 1;
		printf("%d",v[s]);
		--s;
		for(int i = s ; i >= 0 ; --i) {
			printf("%08d",v[i]);
		}
	}
}dp[MAXN][MAXN];
bool vis[MAXN][MAXN];
void get(int a,int b) {
	if(a == 0 || b == 0) return;
	if(vis[a][b]) return;
	dp[a][b] = 1;
	vis[a][b] = 1;
	for(int i = 0 ; i <= 51 ; ++i) {
		int ta = S1.ch[a][i],tb = S2.ch[b][i];
		get(ta,tb);
		dp[a][b] = dp[a][b] + dp[ta][tb];
	}
}
void get2(int a,int b,int dep) {
	if(a == 0 || b == 0) return;
	s[dep] = 0;if(dep != 0) printf("%s\n",s);
	for(int i = 0 ; i <= 51 ; ++i) {
		s[dep] = ic[i];
		get2(S1.ch[a][i],S2.ch[b][i],dep + 1);
	}
}
void Solve() {
	read(N);read(M);
	scanf("%s%s",x + 1,y + 1);
	read(MK);
	for(char i = 'A' ; i <= 'Z' ; ++i) 
		ci[i] = i - 'A',ic[i - 'A'] = i;
	for(char i = 'a' ; i <= 'z' ; ++i) 
		ci[i] = i - 'a' + 26,ic[i - 'a' + 26] = i;
	for(int i = 1 ; i <= N ; ++i) S1.Insert(x[i]);
	for(int i = 1 ; i <= M ; ++i) S2.Insert(y[i]); 
	if(MK == 1) get2(1,1,0);
	get(1,1);
	dp[1][1].print();enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
   	Solve();
    return 0;
}

今天寫的題解全是FJOI啊(其實還寫了2道JOI的水題,太水了不寫題解了) zxg說讓咱們看看數學相關的集訓隊論文,而後作作FJ和SC的省選= = FJ貓錕 SC YJQ 咱們都表示絕不理解該省省選題和該省出題人有什麼關係,真的不懂中老年人思惟啊 可是反正都是要<del>無腦</del>提升刷題量嘛(大霧) 量變能帶來質變 ……嗎?code

39天NOI2018打卡ci

相關文章
相關標籤/搜索