我的有序漏斗算法是按照友盟的有序漏斗规则来进行编写这个算法的。此算法的速度达到了O(1),基本完成了最终目的。具体算法见下,当然引用此文希望可以写出从此处引用。
友盟事件序列的计算规则
用户要按照预先定义的事件顺序来完成漏斗。假设先前定义的事件序列是A-B-C-D-E,以下举例说明哪些序列会被算做成功的转化。
(1) 用户完成了A-B-C-D-E,友盟会认为这个用户成功完成了A-B-C-D-E。
(2) 用户完成了A-B-C-F-D-E,友盟会认为这个用户成功完成了A-B-C-D-E,只不过是按松散的顺序完成的。
(3) 用户完成了A-B-C- E,友盟会认为这个用户成功完成了A-B-C。
(4) 用户完成了A-B-C-A-B-C-D-D-E,友盟会认为这个用户成功完成了依次A-B-C-D-E,完成了一次A-B-C-D-E。是按照松散的顺序完成的。
具体C++代码
//A-B-C-D-E漏斗
#include <iostream>
#include <string>
#include<vector>
using namespace std;
int main()
{
//输入的字符串str
string str;
cout << "请输入字符串:" << endl;
getline(cin, str);
cout << "输入的字符串:" << str << endl;
int i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0;
for (int j = 0; j < str.length(); j++)
{
switch (str[j])
{
case 'A':
i1++;
break;
case 'B':
if (i2 < i1)
i2++;
break;
case 'C':
if (i3 < i2)
i3++;
break;
case 'D':
if (i4 < i3)
i4++;
break;
case 'E':
if (i5 < i4)
i5++;
break;
}
}
cout << "完成有效的A次数:" << i1 << endl;
cout << "完成有效的B次数:" << i2 << endl;
cout << "完成有效的C次数:" << i3 << endl;
cout << "完成有效的D次数:" << i4 << endl;
cout << "完成有效的E次数:" << i5 << endl;
cout << "单独完成有效的A次数:" << i1-i2 << endl;
cout << "单独完成有效的AB次数:" << i2-i3 << endl;
cout << "单独完成有效的ABC次数:" << i3-i4 << endl;
cout << "单独完成有效的ABCD次数:" << i4-i5 << endl;
cout << "完成有效的ABCDE次数:" << i5 << endl;
return 0;
}
| A | B | C | D | E |
|---|---|---|---|---|
| A | B | C | D | E |
| A | B | C | D | E |
| A | B | C | D | E |
| A | B | C | D | E |
| A | B | |||
| A | ||||
| A | ||||
| A | ||||
| A | ||||
| A |
大致的意思的先设定一个ABCDE这几个字母作为数量标志位
i1=A;i2=B;i3=C;i4=D;i5=E;当然这是在完成A-B-C-D-E这一个流程下的ABCDE数量,所对应的输出就是指完成有效的。而单独有效指的是完成上一个流程之外的。
而算法的思想在于选择有效的ABCDE,用于记录下有效的ABCDE的个数。用一个更加简单的说法,填表格
比如我们遇到的一串字符串
"ABCDE ADECA BCDED ACCDE ABACD EACDA EBACD EBA"
我们用填表格来数一下
| A | B | C | D | E |
|---|---|---|---|---|
| A | B | C | D | E |
| A | B | C | D | E |
| A | B | C | D | E |
| A | B | C | D | E |
| A | B | |||
| A | ||||
| A | ||||
| A | ||||
| A | ||||
| A |
那么我们可以清楚的从图中看出我们完成了4个有效的A-B-C-D-E的过程
单独完成A-B的流程1次,单独有效的完成A的流程5次。
然后完成有效的A 10次,B 5次,C 4次,D 4次,E 4次。
并且可以依次类推,增加或者减少节点个数。
Java版本
public class FunnelOrder {
public static void main(String[] argvs){
String userPath = "A-B-C-A-B-C-D-D-E"; //用户实际完成路径
String[] path = userPath.split("-");
// 创建4个标量,用来统计有用的ABCD个数
int i1 = 0, i2 = 0, i3 = 0, i4 = 0 , i5=0;
//A>=B>=C>=D 的数量.所有用户完成的路径元素,遍历.拿到当前的元素.比如B,看数量是否小于A,如果小,说明之前计数了A(B的下标一定大于A)以此类推
for (int j = 0; j < path.length; j++)
{
switch (path[j])
{
case "A":
i1++;
break;
case "B":
if (i2 < i1)
{
i2++;
}
break;
case "C":
if (i3 < i2)
{
i3++;
}
break;
case "D":
if (i4 < i3)
{
i4++;
}
break;
case "E":
if (i5 < i4)
{
i5++;
}
break;
}
}
System.out.println("完成有效的A次数:"+i1);
System.out.println("完成有效的B次数:"+i2);
System.out.println("完成有效的C次数:"+i3);
System.out.println("完成有效的D次数:"+i4);
System.out.println("完成有效的E次数:"+i5);
System.out.println("单独完成有效的A次数:"+(i1-i2));
System.out.println("单独完成有效的AB次数:"+(i2-i3));
System.out.println("单独完成有效的ABC次数:"+(i3-i4));
System.out.println("单独完成有效的ABCD次数:"+(i4-i5));
System.out.println("单独完成有效的ABCDE次数:"+i5);
}
}
特别感谢大佬 “热血沸腾”的Java版本和对我的帮助