Cyclically Isomorphic hdu7279

Problem - 7279

题目大意:有n个长度为m的字符串,对每个字符串都可以进行右移操作,例如abc右移一位变为bca,有q次询问,每次问两个字符串能否使用任意次右移操作使其相等

1<=n*m<=1e5;1<=q<=1e5

思路:如果一字符串s1能通过右移操作变成s2,那么s1一定是s2+s2的子串,因为要知道任意两个字符串是否符合条件,那么就相当于对于每个字符串si,我们得到他的匹配串为si+si,然后将其他字符串sj作为模式串,能成功匹配的,两个字符串就可以相等,所以我们将所有原始字符擦混放入AC自动机中,然后将每个字符串的两倍作为匹配串去匹配,就能得到任意两个字符串是否能相等,时间复杂度O(n*m)

#include
#include
#include
#include
#include
using namespace std;
const int N = 1e6 + 5;
int tr[N][26], fail[N];
vectornum[N];
int cnt = 0;
string s[N];
map, bool>ma;
int n, m;
void init()
{//初始化字典树
	memset(tr[0], 0, sizeof tr[0]);
	cnt = 0;
	for (int i = 0; i <= n * m; i++)
	{
		num[i].clear();
	}
	ma.clear();
}
void insert(string s,int x)
{//建立字典树
	int n = s.length(), root = 0;
	for (int i = 0; i <= n-1; i++)
	{
		if (!tr[root][s[i] - 'a'])
		{
			tr[root][s[i] - 'a'] = ++cnt;
			memset(tr[cnt], 0, sizeof tr[cnt]);
		}
		root = tr[root][s[i] - 'a'];
	}
	num[root].push_back(x);//每个单词的末尾做标记,这里是编号为x的字符串的末尾
}
void getfail()
{//添加失配指针
	queueq;
	for (int i = 0; i < 26; i++)
	{
		if (tr[0][i])
		{
			q.push(tr[0][i]);
			fail[tr[0][i]] = 0;
		}
	}
	while (!q.empty())
	{
		int now = q.front();

		q.pop();
		for (int i = 0; i < 26; i++)
		{
			if (tr[now][i])
			{
				fail[tr[now][i]] = tr[fail[now]][i];
				q.push(tr[now][i]);
			}
			else
			{
				tr[now][i] = tr[fail[now]][i];
			}
		}
	}
}

void find(string s,int x)
{//查找出现过多少个单词
	int root = 0, len = s.length();
	for (int i = 0; i < len; i++)
	{
		root = tr[root][s[i] - 'a'];
		int tmp = root;
		while (tmp)
		{
			for (int j = 0; j < num[tmp].size(); j++)
			{//一个点可能是多个字符串的末尾
				ma[make_pair(x, num[tmp][j])] = 1;//将匹配的位置作为数对存起来
			}
			
			tmp = fail[tmp];
		}
	}
}
int main()
{
	int t;
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> t;

	while (t--)
	{

		cin >> n >> m;
		init();
		for (int i = 1; i <= n; i++)
		{
			cin >> s[i];
			insert(s[i], i);//将原始字符串放入字典树
		}
		getfail();
		for (int i = 1; i <= n; i++)
		{
			find(s[i] + s[i], i);//将每个字符串的两倍作为匹配串
		}
		int q;
		cin >> q;
		for (int i = 1; i <= q; i++)
		{
			int x, y;
			cin >> x >> y;
			if (ma.find(make_pair(x, y)) != ma.end())
			{//直接在存好的map中查找
				cout << "Yes" << endl;
			}
			else
				cout << "No" << endl;
		}
	}
	return 0;
}

你可能感兴趣的:(字符串,算法,c++,数据结构)