[kmp][循环节]Common Divisors CF182D

Vasya has recently learned at school what a number's divisor is and decided to determine a string's divisor. Here is what he came up with.

String a is the divisor of string b if and only if there exists a positive integer x such that if we write out string a consecutively x times, we get string b. For example, string "abab" has two divisors — "ab" and "abab".

Now Vasya wants to write a program that calculates the number of common divisors of two strings. Please help him.

Input

The first input line contains a non-empty string s1.

The second input line contains a non-empty string s2.

Lengths of strings s1 and s2 are positive and do not exceed 105. The strings only consist of lowercase Latin letters.

Output

Print the number of common divisors of strings s1 and s2.

Examples

input

abcdabcd
abcdabcdabcdabcd

output

2

input

aaa
aa

output

1

Note

In first sample the common divisors are strings "abcd" and "abcdabcd".

In the second sample the common divisor is a single string "a". String "aa" isn't included in the answer as it isn't a divisor of string "aaa".

题意: 给出两字符串,询问两串有多少个公共循环部分。例如串abababab中,ab、abab、abababab都是循环部分。

分析: 首先考虑一个字符串的循环部分一定是由一个或多个最小循环部分连接而成。还是在串abababab中,ab是最小循环部分,abab和abababab是循环部分,显然循环部分都是由最小循环部分组成的。因此可以求出两串的最小循环部分,如果最小循环部分都不同那么两串一定不具有公共的循环部分。当两串最小循环部分相同时,记录下最小循环部分分别在两串中出现次数t1、t2。由于t1、t2的每个因子都分别代表一个循环部分,因此最终答案即为t1、t2公因子个数。还有些小细节详见代码。

具体代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;

char s1[100005], s2[100005];
int _next1[100005], _next2[100005];

signed main()
{
	scanf("%s%s", s1+1, s2+1);
	int len1 = strlen(s1+1), len2 = strlen(s2+1);
	for(int i = 2, j = 0; i <= len1; i++)
	{
		while(j && s1[j+1] != s1[i])
			j = _next1[j];
		if(s1[j+1] == s1[i])
			j++;
		_next1[i] = j;
	}
	for(int i = 2, j = 0; i <= len2; i++)
	{
		while(j && s2[j+1] != s2[i])
			j = _next2[j];
		if(s2[j+1] == s2[i])
			j++;
		_next2[i] = j;
	}
	int t1 = len1-_next1[len1], t2 = len2-_next2[len2];//最小循环部分长度 
	if(len1 % t1 != 0)//可能会出现ab|ab|a这样的串,需要进一步修正 
		t1 = len1;
	if(len2 % t2 != 0)
		t2 = len2;
	s1[t1+1] = '\0', s2[t2+1] = '\0';
	int ans = 0;
	if(strcmp(s1+1, s2+1) == 0)//如果最小循环部分相同,则统计答案,否则答案直接为0 
	{
		int up = max(len1, len2)/t1, down = min(len1, len2)/t1;//最小循环部分出现次数 
		for(int i = 1; i <= down; i++)
		{
			if(up % i == 0 && down % i == 0)
				ans++;
		}
		cout << ans;
	}
	else
		puts("0");
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值