大致题意:
a~z每个字符分辅音和元音C和V,给出构词的法则,(pos1,kind1,pos2,kind2)如果位置1是kind1类型的字符,那么位置2必须是kind2类型的字符,求字典序不小于某个给定字符的合法构词(长度和给定的字符相等)若不存在输出-1
长度n<200,构词法则最多4*n*(n-1)条
思路:
可以贪心枚举每一位,假设前pos位答案和给定字符相等,那么pos+1位的字符必须比给定的字符pos+1位的字符大,然后pos+1位以后填充满足类型的最小字符
这样可以用2-sat dfs来输出解,2-sat dfs判解就有这个好处,可以按某种贪心(比如字典序)选解,然后构造出可行解
所以复杂度是 O(枚举*dfs) = O(n*m) = 1e6
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
#include <bitset>
#include <algorithm>
#define SZ(x) ((int)(x).size())
#define ALL(v) (v).begin(), (v).end()
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
#define reveach(i, v) for (__typeof((v).rbegin()) i = (v).rbegin(); i != (v).rend(); ++ i)
#define REP(i,n) for ( int i=1; i<=int(n); i++ )
#define rep(i,n) for ( int i=0; i< int(n); i++ )
using namespace std;
typedef long long ll;
#define X first
#define Y second
typedef pair<int,int> pii;
template <class T>
inline bool RD(T &ret) {
char c; int sgn;
if (c = getchar(), c == EOF) return 0;
while (c != '-' && (c<'0' || c>'9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
template <class T>
inline void PT(T x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) PT(x / 10);
putchar(x % 10 + '0');
}
const int N = 433;
bool val[26];
int n,m;
vector<int>G[N];
void add_edge(int u,char ch1,int v,char ch2){
u = (u-1)*2+(ch1 == 'C');
v = (v-1)*2+(ch2 == 'C');
G[u].push_back(v);
G[v^1].push_back(u^1);
}
int all;
char s[N];
int lim;
bool mark[N];
int sta[N],top;
char ch0,ch1,ch2,ch3;
char tmp[N];
bool dfs(int u) {
if(mark[u^1]) return false;
if(mark[u]) return true;
if( u < 2*lim ){
int id = u/2;
if ( val[s[id]-'a'] != (u&1) ) return false;
}
else if( u/2 == lim ){
if( (u&1) && ch1 == -1) return false;
if( (u&1) == 0 && ch0 == -1) return false;
}else if( u/2 > lim ){
if( (u&1) && ch3 == -1) return false;
if( (u&1) == 0 && ch2 == -1) return false;
}
mark[u] = 1;
sta[++top] = u;
int sz=G[u].size();
for(int i = 0; i < sz;i++) {
int v=G[u][i];
if( dfs(v) == false) return false;
}
return true;
}
bool judge() {
memset(mark,0,sizeof(mark));
for(int i = 0;i < 2*n;i++) {
if(!mark[i]&&!mark[i^1]) {
top = 0;
if( i < 2*lim ){
int id = i/2;
if( val[s[id]-'a'] != (i&1) ) continue;
if( dfs(i) == false ) return false;
}else{
int u = i/2;
if( u == lim){
if( val[s[lim]-'a'+1] != (i&1) ) continue;
else{
if(dfs(i) == false) {
for(int j = 1;j <= top; j++) mark[sta[j]] = 0;
top = 0;
if(dfs(i^1) == false) return false;
}
}
}else{
if( val[0] != (i&1) ) continue;
else{
if(dfs(i) == false) {
for(int j = 1;j <= top; j++) mark[sta[j]] = 0;
top = 0;
if(dfs(i^1) == false) return false;
}
}
}
}
}
}
return true;
}
int main(){
scanf("%s",tmp);
cin>>n>>m;
for(int i = 0; tmp[i]; i++){
if( tmp[i] == 'V') val[i] = 0;
else val[i] = 1;
}
all = strlen(tmp);
REP(i,m){
char ch1,ch2;
int u,v;
scanf("%d %c %d %c",&u,&ch1,&v,&ch2);
add_edge(u,ch1,v,ch2);
}
scanf("%s",s);
for(lim = n; lim >= 0; lim--){
if( s[lim] == 'a'+all-1 ) continue;
ch0 = -1,ch1 = -1;
for(int i = all-1; i > s[lim]-'a'; i--){
if( val[i] == 0) ch0 = 'a'+i;
else ch1 = 'a'+i;
}
if( ch0 == -1 && ch1 == -1 ) continue;
ch2 = -1,ch3 = -1;
for(int i = all-1; i >= 0; i--){
if( val[i] == 0) ch2 = 'a'+i;
else ch3 = 'a'+i;
}
if( judge() ){
rep(i,n) {
if( i < lim ) putchar(s[i]);
else{
int u = 2*i;
if( i == lim){
if( mark[u] ) putchar(ch0);
else putchar(ch1);
}else{
if( mark[u] ) putchar(ch2);
else putchar(ch3);
}
}
}
puts("");
return 0;
}
}
puts("-1");
return 0;
}