poj 字符串相关之1816 Wild Words
一看到字符串匹配的问题,就想到了之前做的动态规划的问题,转移状态公式为:
if (pattern[j][x] == '?' || pattern[j][x] == words[i][y])
dp[x][y] = dp[x - 1][y - 1];
if (pattern[j][x] == '*')
{
for (k = y; k >= 0; k--)
if (dp[x - 1][k])
{
dp[x][y] = 1;
break;
}
}
于是得到了以下代码,每一个pattern和word之间匹配用dp
#include<cstdio>
#include<string>
#include<iostream>
#include<algorithm>
#include<memory.h>
#include<map>
#define PNUM 100005
#define WNUM 105
using namespace std;
char pattern[PNUM][7], words[WNUM][21];
bool dp[7][21];
int N, M;
int main()
{
int i, j, x, y, k, t, count;
scanf("%d%d", &N, &M);
for (i = 0; i < N; i++)
scanf("%s", pattern[i] + 1);
for (i = 0; i < M; i++)
scanf("%s", words[i] + 1);
for (i = 0; i < M; i++)
{
count = 0;
for (j = 0; j < N; j++)
{
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for (x = 1; x <= strlen(pattern[j] + 1); x++)
for (y = 0; y <= strlen(words[i] + 1); y++)
{
if (pattern[j][x] == '?' || pattern[j][x] == words[i][y])
dp[x][y] = dp[x - 1][y - 1];
if (pattern[j][x] == '*')
{
for (k = y; k >= 0; k--)
if (dp[x - 1][k])
{
dp[x][y] = 1;
break;
}
}
}
if (dp[strlen(pattern[j] + 1)][strlen(words[i] + 1)])
{
printf("%d ", j);
count++;
}
}
if (count > 0)
printf("\n");
else
printf("Not match\n");
}
}
不幸的是超时了,因为数据量很大,于是想到了通配符还可以做的是Trie树。代码如下
#include<cstdio>
#include<string>
#include<iostream>
#include<algorithm>
#include<memory.h>
#include<vector>
#include<map>
#define PNUM 100005
using namespace std;
char words[25], pattern[10];
bool result[PNUM];
int N, M;
class node
{
public:
vector<int> index;
node* next[28];
node()
{
for (int i = 0; i < 28; i++)
next[i] = NULL;
}
};
class Trie
{
public:
node* root;
Trie()
{
root = new node();
}
void insert(int id, char * s)
{
node* curr = root;
int i, j, len;
len = strlen(s);
for (i = 0; i < len; i++)
{
if (s[i] == '?')//26
{
if (curr->next[26] == NULL)
curr->next[26] = new node();
j = 26;
}
else if (s[i] == '*')
{
if (curr->next[27] == NULL)
curr->next[27] = new node();
j = 27;
}
else
{
j = s[i] - 'a';
if (curr->next[j] == NULL)
curr->next[j] = new node();
}
curr = curr->next[j];
}
curr->index.push_back(id);
}
void find(char * s, node* root, int i)
{
if (i == strlen(s))
{
node* curr = root;
while (curr != NULL)
{
if (curr->index.size())
for (int t = 0; t < curr->index.size(); t++)
result[curr->index[t]] = 1;
curr = curr->next[27];
}
return;
}
if (root->next[s[i] - 'a'] != NULL)
find(s, root->next[s[i] - 'a'], i + 1);
if (root->next[26] != NULL)
find(s, root->next[26], i + 1);
int t;
for (t = i; t <= strlen(s); t++)
if (root->next[27] != NULL)
find(s, root->next[27], t);
}
};
int main()
{
//freopen("1.txt", "r", stdin);
Trie T;
int i, j, x, y, k, t, count;
scanf("%d%d", &N, &M);
getchar();
for (i = 0; i < N; i++)
{
gets(pattern);
T.insert(i, pattern);
}
for (i = 0; i < M; i++)
{
count = 0;
memset(result, 0, sizeof(result));
gets(words);
T.find(words, T.root, 0);
for (j = 0; j < N; j++)
if (result[j])
{
if (count)
printf(" ");
printf("%d", j);
count++;
}
if (count == 0)
printf("Not match");
puts("");
}
}
注意一下就是pattern可能有重复的,所以记录pattern信息的时候用一下vector
2756K 375M
总结了一下!!!!字符串相关,数据量比较大的时候首先应该考虑字典树。