zoukankan      html  css  js  c++  java
  • 【Luogu P4762】[CERC2014]Virus synthesis

    [CERC2014]Virus synthesis:

    题目大意:

    初始有一个空串,利用下面的操作构造给定串 (S)

    1、串开头或末尾加一个字符

    2、串开头或末尾加一个该串的逆串

    求最小化操作数, (|S| leq 10^5)

    思路:

    回文自动机好题。在求出失配指针时,求出 (mathrm{trans}_i) 表示以 (i) 结尾的回文串后半段起始位置。

    然后可以在回文树上 DP,设 (f_i) 表示变成 (i) 串的最小代价。

    那么有:

    [egin{aligned} f_u&leftarrow f_{mathrm{trans}_u} + 1 + frac{mathrm{len}_u}{2} - mathrm{len}_{mathrm{trans}_u}\ f_u&leftarrow f_{mathrm{fa}_u}+1 end{aligned} ]

    那么 (u) 串的贡献为 (n+f_u-mathrm{len}_u)

    代码:

    const int N = 1e5 + 10;
    
    inline ll Read()
    {
    	ll x = 0, f = 1;
    	char c = getchar();
    	while (c != '-' && (c < '0' || c > '9')) c = getchar();
    	if (c == '-') f = -f, c = getchar();
    	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
    	return x * f;
    }
    
    int t;
    char s[N];
    
    int Code(char c)
    {
    	switch (c)
    	{
    		case 'A': return 1;
    		case 'G': return 2;
    		case 'C': return 3;
    		case 'T': return 4;
    	}
    }
    
    AK PAM
    {
    	int s[N], len[N], trans[N], fail[N], t[N][26];
    	int tot, lst, n;
    	int f[N], ans;
    	int New(int x)
    	{
    		len[++tot] = x;
    		return tot;
    	}
    	void Build()
    	{
    		for (int i = 0; i <= tot; i++)
    			for (int j = 1; j <= 4; j++)
    				t[i][j] = 0;
    		tot = -1, n = 0;
    		New(0), New(-1);
    		s[0] = -1, fail[0] = 1;
    	}
    	
    	int Find(int x)
    	{
    		while (s[n - 1 - len[x]] != s[n]) x = fail[x];
    		return x;
    	}
    	
    	void Insert(int x)
    	{
    		s[++n] = x;
    		int cur = Find(lst);
    		if (!t[cur][x])
    		{
    			int now = New(len[cur] + 2),
    			tmp = Find(fail[cur]);
    			fail[now] = t[tmp][x];
    			t[cur][x] = now;
    			if (len[now] <= 2) trans[now] = fail[now];
    			else
    			{
    				tmp = trans[cur];
    				while (s[n - 1 - len[tmp]] != s[n] || (len[tmp] + 2 << 1) > len[now]) tmp = fail[tmp];
    				trans[now] = t[tmp][x];
    			}
    		}
    		lst = t[cur][x];
    	}
    	void Solve(int n)
    	{
    		queue<int> q;
    		for (int i = 1; i <= 4; i++)
    			if (t[0][i]) q.push(t[0][i]);
    		for (int i = 2; i <= tot; i++) f[i] = len[i];
    		while (!q.empty())
    		{
    			int u = q.front(); q.pop();
    			f[u] = min(f[u], f[trans[u]] + 1 + len[u] / 2 - len[trans[u]]);
    			ans = min(ans, n - len[u] + f[u]);
    			for (int i = 1; i <= 4; i++)
    				if (t[u][i])
    				{
    					int v = t[u][i];
    					f[v] = min(f[v], f[u] + 1);
    					q.push(v);
    				}
    		}
    	}
    }
    
    
    int main()
    {
    //	freopen(".in", "r", stdin);
    //	freopen(".out", "w", stdout);
    	for (t = Read(); t--; )
    	{
    		scanf ("%s", s + 1);
    		PAM::Build();
    		int len = strlen(s + 1);
    		for (int i = 1; i <= len; i++)
    			PAM::Insert(Code(s[i]));
    		PAM::ans = len;
    		PAM::Solve(len); 
    		printf ("%d
    ", PAM::ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    修复文件系统
    遗忘root密码,对密码进行重置
    grub引导程序破坏修复下
    模拟Grub引导故障上(配置文件损坏)
    模拟MBR故障修复
    RAID5 制作 (一个硬盘制作)
    RAID10 (硬盘制作)
    du,df区别
    07_软件的安装
    06_find-查找文件
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/15152669.html
Copyright © 2011-2022 走看看