首先,介绍一些概念:
- 星形邻居物化模型:分为相交的和不相交的,不相交的用处更大,更实用
-
首先人为规定临近距离,黑色实现就表示具有星型临近关系。
从A的每个实例开始计算,他的邻居实例包括自己已经在内的所有实例,同时邻居实例要比中心实例的字母序大。例如A.3的邻居实例里就不会出现A.4,因为A的字母序没有大于A。
- 为什么是无连接算法:应用星型划分模型,使用实例查找机制代替实例连接机制。
- 星型实例:空间实例子集中,所有的实例都是第一个实例的邻居,且这些实例的特征类型是不同的,就称为星型实例。
- 属性级过滤:如果一个co-location模式的任意子集不是频繁的,那么这个候选就可以被剪枝掉。
- 粗糙过滤:产生了所有的星型实例后进行,如果参与度不满足所给阈值,这一候选模式就可以剪掉了。
- 精细过滤:在检验团后获得真实的参与度,之后与阈值比较进行过滤。
过程太麻烦,不写了,附上代码:
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
double min_prev = 0.3;
char max_trait = 'A';
set<string> trait_set; //存放所有可能的空间特征
map< char, int> characNum; //每个空间特征的实例个数
set<string> allSet; // 每个空间特征的总计数
struct table{
string name;
vector<vector<string> > instance;
int jie;
set<string> instance_set; // 每个候选模式中某个空间特征的实例的集合
map<char, int> charac_count; // 候选模式中空间特征的计数
};
map<string,table> table_instance; //总体结构
map<char, vector< vector<string> > > star_niber;//存放所有的星型邻居
map<string, vector<string> > graph; //存放图结构
void outPut(){ //输出函数
for (auto it = table_instance.begin(); it != table_instance.end(); it ++) {
cout << it->first << endl;
vector<vector<string>> temp = it->second.instance;
for (int i = 0; i < temp.size(); i++) {
for (int j = 0; j < temp[i].size(); j++) {
cout << temp[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
}
void check(table t){ //检查参与度,并对三阶及其以上的进行精细过滤
bool flag = false;
for (int i = 0; i < t.jie; i ++) {
double prev = double(t.charac_count[t.name[i]]) / double(characNum[t.name[i]]); //检查参与度
if (prev < min_prev) {
flag = true;
break;
}
}
if (flag == true) { //减枝
for (auto it = trait_set.begin(); it != trait_set.end();) {
string str = *it;
if (str.find(t.name) != str.npos) {
trait_set.erase(it++);
}else {
it ++;
}
}
}
if ( t.jie >= 3) { //三阶以上精细过滤
for (int i = 0; i < t.instance.size(); i++) {
bool newFlag = true;
vector<string> temp;
for (int j = 1; j < t.instance[i].size(); j++) {
temp.push_back(t.instance[i][j]);
}
for (auto it = table_instance.begin(); it != table_instance.end(); it ++) {
if (it->second.name == t.name.substr(1)) {
vector <vector<string> > comp = it->second.instance;
for (int k = 0; k < comp.size(); k++) {
if (comp[k] == temp) {
newFlag = false;
}
}
}
}
if (newFlag == true) {
t.instance.erase(t.instance.begin() + i);
}
}
t.instance_set.clear();
t.charac_count.clear();
for (int i = 0; i < t.instance.size(); i ++) { //更新新的参与度
for (int j = 0; j < t.instance[i].size(); j ++) {
t.instance_set.insert(t.instance[i][j]);
}
}
for (auto it = t.instance_set.begin(); it != t.instance_set.end(); it ++) {
string str = *it;
t.charac_count[str[0]] ++;
}
for (int i = 0; i < t.jie; i ++) {
double prev = double(t.charac_count[t.name[i]]) / double(characNum[t.name[i]]);
if (prev < min_prev) {
flag = true;
break;
}
}
}
if (flag == false) { //加入可以输出的map中
table_instance[t.name] = t;
}
}
void create_star_niber(){ //创建星型邻居的表格
for (auto it1 = graph.begin(); it1 != graph.end(); it1 ++) {
char trait = it1->first[0];
if (trait > max_trait) {
max_trait = trait;
}
vector<string>temp;
temp.push_back(it1->first);
for (auto it2 = it1->second.begin(); it2 != it1->second.end(); it2++) {
string str = *it2;
if (str[0] > trait) {
temp.push_back(str);
}
}
sort(temp.begin(), temp.end());
for (int i = 1; i < temp.size(); i++) {
if (temp[i][0] == temp[i-1][0]) { //行实例移项,便于处理
vector<string>newTemp;
newTemp.push_back(temp[0]);
newTemp.push_back(temp[i]);
star_niber[trait].push_back(newTemp);
temp.erase(temp.begin()+i);
}
}
star_niber[trait].push_back(temp);
}
}
map<char,bool> m;
void dfs(string result)
{
bool flag;
if (result.size() > 1) {
for (int i = 0; i < result.size()-1; i++) {
if (result[i] > result[i+1] ) {
flag = true;
}
}
}
if (flag == false || result.size() == 1) {
trait_set.insert(result);
}
for(char c = 'A';c <= max_trait;c++)
{
if(m[c] == false)
{
string s = result + c;
m[c] = true;
dfs(s);
m[c] = false;
}
}
}
void get_trait_set(){ //所有可能的特征
string result = "";
m.clear();
dfs(result);
}
void createTable(string str){ //生成频繁模式
int count = 0;
char center = str[0];
vector< vector<string> > instance;
set<string> instance_set;
vector< vector<string> > niberTable = star_niber[center];
for (auto it1 = niberTable.begin(); it1 != niberTable.end(); it1 ++) {
vector<string> temp = *it1;
vector<string> k;
for (auto it2 = temp.begin(); it2 != temp.end(); it2 ++) {
string t = *it2;
if (t[0] == str[count]) {
count ++;
k.push_back(t);
// instance_set.insert(t);
if (count == str.size()) {
break;
}
}
}
if (k.size() == str.size()) { //避免混入单个
for (int i = 0; i < k.size(); i ++) {
instance_set.insert(k[i]);
}
instance.push_back(k);
}
count = 0;
}
table t;
t.instance = instance;
t.name = str;
t.jie = str.size();
t.instance_set = instance_set;
for (auto it = instance_set.begin(); it != instance_set.end(); it ++) {
string str = *it;
t.charac_count[str[0]] ++;
}
check(t);
}
int main(int argc, char *argv[]) {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
string str1, str2;
cin >> str1 >> str2;
allSet.insert(str1);
graph[str1].push_back(str2);
// graph[str2].push_back(str1);
}
for (auto it = allSet.begin(); it != allSet.end(); it++) {
string str = *it;
characNum[str[0]] ++;
}
create_star_niber();
get_trait_set();
int k = 1;
// for (auto it = star_niber.begin(); it != star_niber.end(); it ++) {
// vector<vector <string> > temp = it->second;
// cout << it->first << endl;
// for (int i = 0; i < temp.size(); i++) {
// for (int j = 0; j < temp[i].size(); j++) {
// cout << temp[i][j] << " ";
// }
// cout << endl;
// }
// }
bool flag = true;
while (flag) {
flag = false;
for (auto it = trait_set.begin(); it != trait_set.end(); it ++) {
string str = *it;
if (str.size() == k) {
createTable(str);
flag = true;
}
}
k++;
}
outPut();
}