最短循环节(KMP)实现

假设字符串str的长度为len,则str存在最小循环节,循环节的长度cycleLen为len-next[len],循环子串为str[0…len-next[len]-1]

  1. 如果len可以被len - next[len]整除,则表明字符串str可以完全由循环节循环组成
  2. 如果不能,说明还需要再添加几个字母才能补全,需要补的个数cycleLen-len%cycleLen,需要补充的字符串为str[len%cycleLen…cycleLen-len%cycleLen]
#include <iostream>
#include <vector>
using namespace std;

/* str 数组的 str.length() + 1 个next数组值 */
void getNext(string& str, vector<int>& next) {
    
    
	next.at(1) = 0;
	if (str.length() == 1) {
    
    
		return;
	}
	for (int i = 2, cn = 0; i <= str.length(); i++) {
    
    
		if (str.at(i - 1) == str.at(cn)) {
    
    
			next.at(i) = ++cn;
		}
		else if (cn == 0) {
    
    
			next.at(i) = 0;
		}
		else {
    
    
			cn = next.at(cn);
		}
	}
}

int main() {
    
    
	string str("0123012301");
	int len = str.length();
	vector<int> next(len + 1, -1);
	getNext(str, next);

	/* 循环节长度 */
	int cycleLen = len - next.at(len);
	cout << "最短循环节长度: " << cycleLen << endl;

	/* 字符串长度对循环节长度取余是0,则为循环字符串,否则需要补充字符  */
	if (len % cycleLen == 0) {
    
    
		cout << "最短循环节是: ";
		cout << str.substr(0, cycleLen).c_str() << endl;
	}
	else {
    
    
		cout << "需要补充的字符: ";
		/* 需要补充的长度为cycleLen - (next.at(len) % cycleLen) */
		cout << str.substr(next.at(len) % cycleLen, cycleLen - (next.at(len) % cycleLen)).c_str() << endl;
	}

	system("pause");
	return 0;
}

如有侵权,请联系删除,如有错误,欢迎大家指正,谢谢

猜你喜欢

转载自blog.csdn.net/xiao_ma_nong_last/article/details/105630994