【AC自动机】 HDOJ 2296 Ring

简单的AC自动机+DP,DP很容易想到。但是这题的输出实在是太恶心了。。。而且这题的数据很弱。。。我交了一发样例都没过的代码都AC了。。。后来把代码改了,自己弄的几组数据测了几下,感觉没什么太大的问题了。。

附一组数据:

1
5 4
s sd d fgf
2 6 4 10

答案是dsdsd。。。

#include <iostream>
#include <sstream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <climits>
#define maxn 1005
#define eps 1e-6
#define mod 10007
#define INF 99999999
#define lowbit(x) ((x)&(-(x)))
#define lson o<<1, L, mid
#define rson o<<1 | 1, mid+1, R
typedef long long LL;
using namespace std;

char str[105][20];
int num[105];
struct trie
{
	int next[maxn][26];
	int fail[maxn];
	int end[maxn];
	int loc[maxn];
	queue<int> q;
	int top, root, now;
	
	int newnode(void)
	{
		fail[top] = -1;
		end[top] = 0;
		for(int i = 0; i < 26; i++)
			next[top][i] = -1;
		return top++;
	}
	void init(void)
	{
		top = 0;
		root = newnode();
	}
	void insert(char *s, int x)
	{
		int len = strlen(s), i, k;
		now = root;
		for(i = 0; i < len; i++) {
			k = s[i] - 'a';
			if(next[now][k] == -1)
				next[now][k] = newnode();
			now = next[now][k];
			loc[now] = k;
		}
		end[now] = x;
	}
	void build(void)
	{
		now = root;
		for(int i = 0; i < 26; i++) {
			if(next[now][i] == -1)
				next[now][i] = root;
			else {
				fail[next[now][i]] = root;
				q.push(next[now][i]);
			}
		}
		while(!q.empty()) {
			now = q.front();
			q.pop();
			if(end[fail[now]]) end[now] += end[fail[now]];
			for(int i = 0; i < 26; i++)
				if(next[now][i] == -1)
					next[now][i] = next[fail[now]][i];
				else {
					fail[next[now][i]] = next[fail[now]][i];
					q.push(next[now][i]);
				}
		}
	}
}tmp;
int dp[105][maxn];
bool vis[105][maxn];
int loc[105][maxn];
string a[55][maxn];
char b[maxn];
int n, m;

inline int cal(int i, int j)
{
	return (i-1)*m+j;
}
void init(void)
{
	memset(dp, 0, sizeof dp);
	memset(vis, 0, sizeof vis);
	memset(loc, 0, sizeof loc);
	for(int i = 0; i < 55; i++)
		for(int j = 0; j < maxn; j++)
			a[i][j].clear();
}
void read(void)
{
	int i;
	tmp.init();
	scanf("%d%d", &n, &m);
	for(i = 0; i < m; i++) scanf("%s", str[i]);
	for(i = 0; i < m; i++) scanf("%d", &num[i]);
	for(i = 0; i < m; i++) tmp.insert(str[i], num[i]);
	tmp.build();
}
void work(void)
{
	int i, j, k, ans, res, tmpi, tmpj;
	vis[0][0] = true;
	for(i = 0; i < n; i++)
		for(j = 0; j < tmp.top; j++)
			if(vis[i][j])
				for(k = 0; k < 26; k++) {
					b[0] = tmp.loc[tmp.next[j][k]]+'a';
					b[1]='\0';
					if(dp[i+1][tmp.next[j][k]] == dp[i][j] + tmp.end[tmp.next[j][k]] && loc[i+1][tmp.next[j][k]]) {
						if(a[i+1][tmp.next[j][k]] > a[i][j] + b)
							a[i+1][tmp.next[j][k]] = a[i][j] + b;
						vis[i+1][tmp.next[j][k]] = true;
					}
					if(dp[i+1][tmp.next[j][k]] < dp[i][j] + tmp.end[tmp.next[j][k]] || loc[i+1][tmp.next[j][k]] == 0) {
						loc[i+1][tmp.next[j][k]] = 1;
						a[i+1][tmp.next[j][k]] = a[i][j] + b;
						dp[i+1][tmp.next[j][k]] = dp[i][j] + tmp.end[tmp.next[j][k]];
						vis[i+1][tmp.next[j][k]] = true;
					}
				}
	ans = 0;
	for(i = 0; i < tmp.top; i++)
		if(ans < dp[n][i])
			ans = dp[n][i], res = i;
	tmpi = n, tmpj = res;
	if(ans == 0) {
		printf("\n");
		return;
	}
	for(i = n; i >= 1; i--){
		res = 0;
		for(j = 0; j < tmp.top; j++) {
            if(res < dp[i][j]) res = dp[i][j];
			if(ans == dp[i][j]) {
				if(tmpi > i)
					tmpi = i, tmpj = j;
				else if(a[tmpi][tmpj] > a[i][j])
					tmpi = i, tmpj = j;
			}
		}
		if(res != ans) break;
	}
	printf("%s\n", a[tmpi][tmpj].c_str());
}
int main(void)
{
	int _;
	while(scanf("%d", &_)!=EOF){
		while(_--) {
			init();
			read();
			work();
		}
	}
	return 0;
}


你可能感兴趣的:(dp,HDU,AC自动机)