HDU 3913 Suffix

SUFFIX
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 85 Accepted Submission(s): 27


Problem Description
A string is a list of characters containing only letter ‘a’ to ‘z’. For example: “abcdefg”, “isun” are valid strings. “rocket323” is not a valid string.

A suffix of a string suf[i] is the list of characters at positions from i to n-1 (positions are labeled from 0 to n – 1, n is length of the string). For the string “hustacm”, suf[0] = “hustacm”, suf[1] = “ustacm”, suf[3] = “tacm”, suf[6] = “m”.

The suffix list L of a string is a permutation of numbers from 0 to n-1(n is length of the string), which satisfy the following condition:
suf[L[0]] < suf[L[1]] < suf[L[2]] < … < suf[L[n-1]].

For the string “aabac”, its suffix list is [0, 1, 3, 2, 4].
Here comes the question: Given a string S and a suffix list L, you are to change minimum number of characters of S so that the suffix list of the new string is equal to L.


Input
There are multiple cases, for each case:
The first line is integer n representing the length of the string. (1 <= n <= 500)
The second line is the string.
The third line is a permutation of numbers from 0 to n-1.


Output
For each case, output the minimum number of characters to change in order to satisfy the condition above, if there is no solution, just output -1.


Sample Input
3
abc
0 1 2
3
aab
2 0 1


Sample Output
0

2

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXV 500
#define MAXE 1000
#define INF 0x7fffffff

int list[MAXV];
char s[MAXV];
int f[MAXV + 1][26];
bool equal[MAXV];
int n;

struct Edge {
    int ed, next;
} edge[MAXE];

int head[MAXV], nEdge;

void init() {
    memset(head, 0xff, sizeof(head));
    nEdge = 0;
}

void addEdge(const int a, const int b) {
    edge[nEdge].ed = b;
    edge[nEdge].next = head[a];
    head[a] = nEdge++;
}

bool find(int cur, int tar){
	int i, p;
	if (cur >= n) return false;
	if (tar >= n) return true;
	for (i = head[cur]; ~i; i = edge[cur].next){
		p = edge[i].ed;
		if (p == tar) return true;
		return find(p, tar);
	}
	return false;
}

int imin(int a, int b){
	return a < b ? a : b;
}

void calc(){
	int i, j, k;
	for (i = 0; i < n - 1; i++){
		equal[i] = find(list[i + 1] + 1, list[i] + 1);
	}
	equal[i] = true;
	for (i = n - 1; i >= 0; i--){
		for (j = 0; j < 26; j++){
			f[i][j] = n + 1;
			for (k = j + 1 - equal[i]; k < 26; k++){
				f[i][j] = imin(f[i + 1][k], f[i][j]);
			}
			if (s[list[i]] != j + 'a') f[i][j]++;
		}
	}
	
	j = n + 1;
	for (i = 0; i < 26; i++)
		j = imin(j, f[0][i]);
	if (j > n) j = -1;
	printf("%d\n", j);
}

int main(){
	int i;
	while(scanf("%d", &n) != EOF){
		scanf("%s", s);
		init();
		memset(f, 0, sizeof(f));
		memset(equal, 0, sizeof(equal));
		for (i = 0; i < n; i++) scanf("%d", &list[i]);
		for (i = 0; i < n - 1; i++){
			addEdge(list[i + 1], list[i]);
		}
		calc();
	}
	return 0;
}
/******************
dp
转移规律不好找,字符串之间比大小,转移起来不好搞,但这题比较的都是后缀关系的字符串
根据list,从a[n-1]和a[n-2]的大小关系开始推一推,会发现其实每个字符之间的大小关系都是确定的
a[list[i]] < a[list[i + 1] 或者 a[list[i]] <= a="" 1="" f="" min="" 1="" k=""> j 或者 k >= j} + (str[list[i]] != j)

觉得开头要是不推的话,就想不到这些...
******************/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值